diff options
| author | Kai Germaschewski <kai@tp1.ruhr-uni-bochum.de> | 2003-01-24 09:54:04 -0600 |
|---|---|---|
| committer | Kai Germaschewski <kai@tp1.ruhr-uni-bochum.de> | 2003-01-24 09:54:04 -0600 |
| commit | dcc38eae49e06d798497373771ae03f5508a2ec7 (patch) | |
| tree | 5f2ea4f7f329bff12bc4c1d2da2f5186344c452b | |
| parent | e4ccd604a353b3d4e61e99d04ac9a2bdd8b66ec4 (diff) | |
kbuild/modules: Record versions for unresolved symbols
In the case of CONFIG_MODVERSIONING, the build step will only
generate preliminary <module>.o objects, and an additional
postprocessing step is necessary to record the versions of the unresolved
symbols and add them into the final <module>.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 <module>.ko using the preliminary <module.o> + 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.
| -rw-r--r-- | Makefile | 15 | ||||
| -rw-r--r-- | include/linux/module.h | 7 | ||||
| -rw-r--r-- | scripts/Makefile.modver | 89 |
3 files changed, 108 insertions, 3 deletions
@@ -262,7 +262,7 @@ endif # When we're building modules with modversions, we need to consider # the built-in objects during the descend as well, in order to -# make sure the checksums are uptodate before we use them. +# make sure the checksums are uptodate before we record them. ifdef CONFIG_MODVERSIONING ifeq ($(KBUILD_MODULES),1) @@ -508,8 +508,16 @@ ifdef CONFIG_MODULES # Build modules -.PHONY: modules -modules: $(SUBDIRS) +.PHONY: modules __modversions +modules: $(SUBDIRS) __modversions + +ifdef CONFIG_MODVERSIONING + +__modversions: vmlinux $(SUBDIRS) + @echo ' Recording module symbol versions.'; + $(Q)$(MAKE) -rR -f scripts/Makefile.modver + +endif # Install modules @@ -690,6 +698,7 @@ MRPROPER_FILES += \ # Directories removed with 'make mrproper' MRPROPER_DIRS += \ + $(MODVERDIR) \ .tmp_export-objs \ include/config \ include/linux/modules diff --git a/include/linux/module.h b/include/linux/module.h index af4272910b27..e8726d9909d7 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -33,12 +33,19 @@ #endif #define MODULE_NAME_LEN (64 - sizeof(unsigned long)) + struct kernel_symbol { unsigned long value; const char *name; }; +struct modversion_info +{ + unsigned long crc; + char name[MODULE_NAME_LEN]; +}; + /* These are either module local, or the kernel's dummy ones. */ extern int init_module(void); extern void cleanup_module(void); 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 <linux/module.h>"; \ + 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 |
