From dcc38eae49e06d798497373771ae03f5508a2ec7 Mon Sep 17 00:00:00 2001 From: Kai Germaschewski Date: Fri, 24 Jan 2003 09:54:04 -0600 Subject: kbuild/modules: Record versions for unresolved symbols In the case of CONFIG_MODVERSIONING, the build step will only generate preliminary .o objects, and an additional postprocessing step is necessary to record the versions of the unresolved symbols and add them into the final .ko The version information for unresolved symbols is again recorded into a special section, "__versions", which contains an array of symbol name strings and checksum (struct modversion_info). Size is here not an issue, since this section will not be stored permanently in kernel memory. Makefile.modver takes care of the following steps: o Collect the version information for all exported symbols from vmlinux and all modules which export symbols. o For each module, generate a C file which contains the modversion information for all unresolved symbols in that module. o For each module, compile that C file to an object file o Finally, link the .ko using the preliminary + the version information above. The first two steps are currently done by not very efficient scripting, so there's room for performance improvement using some helper C code. --- scripts/Makefile.modver | 89 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) (limited to 'scripts/Makefile.modver') diff --git a/scripts/Makefile.modver b/scripts/Makefile.modver index 5405cbce2170..372d6aff5a32 100644 --- a/scripts/Makefile.modver +++ b/scripts/Makefile.modver @@ -2,3 +2,92 @@ # Module versions # =========================================================================== +.PHONY: __modversions +__modversions: + +include scripts/Makefile.lib + +# + +modules := $(patsubst ./%,%,$(shell cd $(MODVERDIR); find . -name \*.ko)) + +__modversions: $(modules) + @: + +quiet_cmd_ld_ko_o = LD [M] $@ + cmd_ld_ko_o = $(LD) $(LDFLAGS) $(LDFLAGS_MODULE) -o $@ \ + $(filter-out FORCE,$^) + +init/vermagic.o: ; + +$(modules): %.ko :%.o $(MODVERDIR)/%.o init/vermagic.o FORCE + $(call if_changed,ld_ko_o) + +targets += $(modules) + + +quiet_cmd_cc_o_c = CC $@ + cmd_cc_o_c = $(CC) $(CFLAGS) -c -o $@ $< + +$(addprefix $(MODVERDIR)/,$(modules:.ko=.o)): %.o: %.c FORCE + $(call if_changed,cc_o_c) + +targets += $(addprefix $(MODVERDIR)/,$(modules:.ko=.o)) + +define rule_mkver_o_c + echo ' MKVER $@'; \ + ( echo "#include "; \ + echo ""; \ + echo "static const struct modversion_info ____versions[]"; \ + echo "__attribute__((section(\"__versions\"))) = {"; \ + for sym in `nm -u $<`; do \ + grep "\"$$sym\"" .tmp_all-versions \ + || echo "*** Warning: $(<:.o=.ko): \"$$sym\" unresolved!" >&2;\ + done; \ + echo "};"; \ + ) > $@ +endef + +$(addprefix $(MODVERDIR)/,$(modules:.ko=.c)): \ +$(MODVERDIR)/%.c: %.o .tmp_all-versions FORCE + $(call if_changed_rule,mkver_o_c) + +targets += $(addprefix $(MODVERDIR)/,$(modules:.ko=.o.c)) + +export-objs := $(shell for m in vmlinux $(modules:.ko=.o); do objdump -h $$m | grep -q __ksymtab && echo $$m; done) + +cmd_gen-all-versions = mksyms $(export-objs) +define rule_gen-all-versions + echo ' MKSYMS $@'; \ + for mod in $(export-objs); do \ + modname=`basename $$mod`; \ + nm $$mod \ + | grep ' __crc_' \ + | sed "s/\([^ ]*\) A __crc_\(.*\)/{ 0x\1, \"\2\" }, \/* $$modname *\//g;s/.* w __crc_\(.*\)/{ 0x0 , \"\1\" }, \/* $$modname *\//g"; \ + done > $@; \ + echo 'cmd_$@ := $(cmd_$(1))' > $(@D)/.$(@F).cmd +endef + +.tmp_all-versions: $(export-objs) FORCE + $(call if_changed_rule,gen-all-versions) + +targets += .tmp_all-versions + +# Add FORCE to the prequisites of a target to force it to be always rebuilt. +# --------------------------------------------------------------------------- + +.PHONY: FORCE + +FORCE: + +# Read all saved command lines and dependencies for the $(targets) we +# may be building above, using $(if_changed{,_dep}). As an +# optimization, we don't need to read them if the target does not +# exist, we will rebuild anyway in that case. + +targets := $(wildcard $(sort $(targets))) +cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd)) + +ifneq ($(cmd_files),) + include $(cmd_files) +endif -- cgit v1.2.3