Commit dcc38eae authored by Kai Germaschewski's avatar Kai Germaschewski

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.
parent e4ccd604
......@@ -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
......
......@@ -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);
......
......@@ -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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment