Commit c99e695c authored by Kai Germaschewski's avatar Kai Germaschewski

Hand merged

parents c92cacc2 e24c9231
...@@ -183,6 +183,8 @@ export CPPFLAGS NOSTDINC_FLAGS OBJCOPYFLAGS LDFLAGS ...@@ -183,6 +183,8 @@ export CPPFLAGS NOSTDINC_FLAGS OBJCOPYFLAGS LDFLAGS
export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
export MODVERDIR := .tmp_versions
# The temporary file to save gcc -MD generated dependencies must not # The temporary file to save gcc -MD generated dependencies must not
# contain a comma # contain a comma
depfile = $(subst $(comma),_,$(@D)/.$(@F).d) depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
...@@ -190,7 +192,7 @@ depfile = $(subst $(comma),_,$(@D)/.$(@F).d) ...@@ -190,7 +192,7 @@ depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
noconfig_targets := xconfig menuconfig config oldconfig randconfig \ noconfig_targets := xconfig menuconfig config oldconfig randconfig \
defconfig allyesconfig allnoconfig allmodconfig \ defconfig allyesconfig allnoconfig allmodconfig \
clean mrproper distclean \ clean mrproper distclean \
help tags TAGS sgmldocs psdocs pdfdocs htmldocs \ help tags TAGS cscope sgmldocs psdocs pdfdocs htmldocs \
checkconfig checkhelp checkincludes checkconfig checkhelp checkincludes
RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS \) -prune -o RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS \) -prune -o
...@@ -256,14 +258,22 @@ ifdef include_config ...@@ -256,14 +258,22 @@ ifdef include_config
-include .config.cmd -include .config.cmd
ifdef CONFIG_MODULES
export EXPORT_FLAGS := -DEXPORT_SYMTAB
endif
ifndef CONFIG_FRAME_POINTER ifndef CONFIG_FRAME_POINTER
CFLAGS += -fomit-frame-pointer CFLAGS += -fomit-frame-pointer
endif 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 record them.
ifdef CONFIG_MODVERSIONS
ifeq ($(KBUILD_MODULES),1)
ifneq ($(KBUILD_BUILTIN),1)
KBUILD_BUILTIN := 1
endif
endif
endif
# #
# INSTALL_PATH specifies where to place the updated kernel and system map # INSTALL_PATH specifies where to place the updated kernel and system map
# images. Uncomment if you want to place them anywhere other than root. # images. Uncomment if you want to place them anywhere other than root.
...@@ -384,7 +394,7 @@ $(sort $(vmlinux-objs)): $(SUBDIRS) ; ...@@ -384,7 +394,7 @@ $(sort $(vmlinux-objs)): $(SUBDIRS) ;
# Handle descending into subdirectories listed in $(SUBDIRS) # Handle descending into subdirectories listed in $(SUBDIRS)
.PHONY: $(SUBDIRS) .PHONY: $(SUBDIRS)
$(SUBDIRS): .hdepend prepare $(SUBDIRS): prepare
$(Q)$(MAKE) $(build)=$@ $(Q)$(MAKE) $(build)=$@
# Things we need done before we descend to build or make # Things we need done before we descend to build or make
...@@ -392,6 +402,16 @@ $(SUBDIRS): .hdepend prepare ...@@ -392,6 +402,16 @@ $(SUBDIRS): .hdepend prepare
.PHONY: prepare .PHONY: prepare
prepare: include/linux/version.h include/asm include/config/MARKER prepare: include/linux/version.h include/asm include/config/MARKER
ifdef CONFIG_MODVERSIONS
ifdef KBUILD_MODULES
ifeq ($(origin SUBDIRS),file)
$(Q)rm -rf $(MODVERDIR)
else
@echo '*** Warning: Overriding SUBDIRS on the command line can cause'
@echo '*** inconsistencies with module symbol versions'
endif
endif
endif
@echo ' Starting the build. KBUILD_BUILTIN=$(KBUILD_BUILTIN) KBUILD_MODULES=$(KBUILD_MODULES)' @echo ' Starting the build. KBUILD_BUILTIN=$(KBUILD_BUILTIN) KBUILD_MODULES=$(KBUILD_MODULES)'
# We need to build init/vermagic.o before descending since all modules # We need to build init/vermagic.o before descending since all modules
...@@ -475,61 +495,11 @@ include/linux/version.h: Makefile ...@@ -475,61 +495,11 @@ include/linux/version.h: Makefile
) > $@.tmp ) > $@.tmp
@$(update-if-changed) @$(update-if-changed)
# Generate module versions
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# The targets are still named depend / dep for traditional .PHONY: depend dep
# reasons, but the only thing we do here is generating depend dep:
# the module version checksums. @echo'*** Warning: make $@ is unnecessary now.'
.PHONY: depend dep $(patsubst %,_sfdep_%,$(SUBDIRS))
depend dep: .hdepend
# .hdepend is our (misnomed) marker for whether we've
# generated module versions
make-versions := $(strip $(if $(filter dep depend,$(MAKECMDGOALS)),1) \
$(if $(wildcard .hdepend),,1))
.hdepend: prepare FORCE
ifneq ($(make-versions),)
@$(MAKE) include/linux/modversions.h
@touch $@
endif
ifdef CONFIG_MODVERSIONS
# Update modversions.h, but only if it would change.
.PHONY: __rm_tmp_export-objs
__rm_tmp_export-objs:
@rm -rf .tmp_export-objs
include/linux/modversions.h: $(patsubst %,_modver_%,$(SUBDIRS))
@echo -n ' Generating $@'
@( echo "#ifndef _LINUX_MODVERSIONS_H";\
echo "#define _LINUX_MODVERSIONS_H"; \
echo "#include <linux/modsetver.h>"; \
cd .tmp_export-objs >/dev/null; \
for f in `find modules -name \*.ver -print | sort`; do \
echo "#include <linux/$${f}>"; \
done; \
echo "#endif"; \
) > $@.tmp; \
$(update-if-changed)
.PHONY: $(patsubst %, _modver_%, $(SUBDIRS))
$(patsubst %, _modver_%, $(SUBDIRS)): __rm_tmp_export-objs
$(Q)$(MAKE) -f scripts/Makefile.modver obj=$(patsubst _modver_%,%,$@)
else # !CONFIG_MODVERSIONS
.PHONY: include/linux/modversions.h
include/linux/modversions.h:
endif # CONFIG_MODVERSIONS
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Modules # Modules
...@@ -538,12 +508,16 @@ ifdef CONFIG_MODULES ...@@ -538,12 +508,16 @@ ifdef CONFIG_MODULES
# Build modules # Build modules
.PHONY: modules __modversions
modules: $(SUBDIRS) __modversions
ifdef CONFIG_MODVERSIONS ifdef CONFIG_MODVERSIONS
MODFLAGS += -include include/linux/modversions.h
endif
.PHONY: modules __modversions: vmlinux $(SUBDIRS)
modules: $(SUBDIRS) @echo ' Recording module symbol versions.';
$(Q)$(MAKE) -rR -f scripts/Makefile.modver
endif
# Install modules # Install modules
...@@ -574,6 +548,7 @@ _modinst_post: ...@@ -574,6 +548,7 @@ _modinst_post:
.PHONY: $(patsubst %, _modinst_%, $(SUBDIRS)) .PHONY: $(patsubst %, _modinst_%, $(SUBDIRS))
$(patsubst %, _modinst_%, $(SUBDIRS)) : $(patsubst %, _modinst_%, $(SUBDIRS)) :
$(Q)$(MAKE) -rR -f scripts/Makefile.modinst obj=$(patsubst _modinst_%,%,$@) $(Q)$(MAKE) -rR -f scripts/Makefile.modinst obj=$(patsubst _modinst_%,%,$@)
else # CONFIG_MODULES else # CONFIG_MODULES
# Modules not configured # Modules not configured
...@@ -624,7 +599,7 @@ spec: ...@@ -624,7 +599,7 @@ spec:
rpm: clean spec rpm: clean spec
find . $(RCS_FIND_IGNORE) \ find . $(RCS_FIND_IGNORE) \
\( -size 0 -o -name .depend -o -name .hdepend \) \ \( -size 0 -o -name .depend -o -name .hdepend\) \
-type f -print | xargs rm -f -type f -print | xargs rm -f
set -e; \ set -e; \
cd $(TOPDIR)/.. ; \ cd $(TOPDIR)/.. ; \
...@@ -718,11 +693,12 @@ MRPROPER_FILES += \ ...@@ -718,11 +693,12 @@ MRPROPER_FILES += \
.menuconfig.log \ .menuconfig.log \
include/asm \ include/asm \
.hdepend include/linux/modversions.h \ .hdepend include/linux/modversions.h \
tags TAGS kernel.spec \ tags TAGS cscope kernel.spec \
.tmp* .tmp*
# Directories removed with 'make mrproper' # Directories removed with 'make mrproper'
MRPROPER_DIRS += \ MRPROPER_DIRS += \
$(MODVERDIR) \
.tmp_export-objs \ .tmp_export-objs \
include/config \ include/config \
include/linux/modules include/linux/modules
...@@ -775,6 +751,9 @@ define all-sources ...@@ -775,6 +751,9 @@ define all-sources
-name '*.[chS]' -print ) -name '*.[chS]' -print )
endef endef
quiet_cmd_cscope = MAKE $@
cmd_cscope = $(all-sources) | cscope -k -b -i -
quiet_cmd_TAGS = MAKE $@ quiet_cmd_TAGS = MAKE $@
cmd_TAGS = $(all-sources) | etags - cmd_TAGS = $(all-sources) | etags -
...@@ -787,6 +766,9 @@ define cmd_tags ...@@ -787,6 +766,9 @@ define cmd_tags
$(all-sources) | xargs ctags $$CTAGSF -a $(all-sources) | xargs ctags $$CTAGSF -a
endef endef
cscope: FORCE
$(call cmd,cscope)
TAGS: FORCE TAGS: FORCE
$(call cmd,TAGS) $(call cmd,TAGS)
......
...@@ -1196,11 +1196,7 @@ int zft_compressor_init(void) ...@@ -1196,11 +1196,7 @@ int zft_compressor_init(void)
printk( printk(
KERN_INFO "(c) 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)\n" KERN_INFO "(c) 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)\n"
KERN_INFO "Compressor for zftape (lzrw3 algorithm)\n" KERN_INFO "Compressor for zftape (lzrw3 algorithm)\n"
KERN_INFO "Compiled for kernel version %s" KERN_INFO "Compiled for kernel version %s\n", UTS_RELEASE);
#ifdef MODVERSIONS
" with versioned symbols"
#endif
"\n", UTS_RELEASE);
} }
#else /* !MODULE */ #else /* !MODULE */
/* print a short no-nonsense boot message */ /* print a short no-nonsense boot message */
......
...@@ -70,11 +70,7 @@ KERN_INFO "(c) 1993-1996 Bas Laarhoven (bas@vimec.nl)\n" ...@@ -70,11 +70,7 @@ KERN_INFO "(c) 1993-1996 Bas Laarhoven (bas@vimec.nl)\n"
KERN_INFO "(c) 1995-1996 Kai Harrekilde-Petersen (khp@dolphinics.no)\n" KERN_INFO "(c) 1995-1996 Kai Harrekilde-Petersen (khp@dolphinics.no)\n"
KERN_INFO "(c) 1996-1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)\n" KERN_INFO "(c) 1996-1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)\n"
KERN_INFO "QIC-117 driver for QIC-40/80/3010/3020 floppy tape drives\n" KERN_INFO "QIC-117 driver for QIC-40/80/3010/3020 floppy tape drives\n"
KERN_INFO "Compiled for Linux version %s" KERN_INFO "Compiled for Linux version %s\n", UTS_RELEASE);
#ifdef MODVERSIONS
" with versioned symbols"
#endif
"\n", UTS_RELEASE);
} }
#else /* !MODULE */ #else /* !MODULE */
/* print a short no-nonsense boot message */ /* print a short no-nonsense boot message */
......
...@@ -331,11 +331,7 @@ KERN_INFO ...@@ -331,11 +331,7 @@ KERN_INFO
KERN_INFO KERN_INFO
"and builtin compression (lzrw3 algorithm).\n" "and builtin compression (lzrw3 algorithm).\n"
KERN_INFO KERN_INFO
"Compiled for Linux version %s" "Compiled for Linux version %s\n", UTS_RELEASE);
#ifdef MODVERSIONS
" with versioned symbols"
#endif
"\n", UTS_RELEASE);
} }
#else /* !MODULE */ #else /* !MODULE */
/* print a short no-nonsense boot message */ /* print a short no-nonsense boot message */
......
...@@ -42,12 +42,6 @@ ...@@ -42,12 +42,6 @@
* POSSIBILITY OF SUCH DAMAGES. * POSSIBILITY OF SUCH DAMAGES.
*/ */
/*
* This is the only file where module.h should
* embed module global version info.
*/
#define AHD_MODVERSION_FILE
#include "aic79xx_osm.h" #include "aic79xx_osm.h"
#include "aic79xx_inline.h" #include "aic79xx_inline.h"
#include <scsi/scsicam.h> #include <scsi/scsicam.h>
......
...@@ -50,9 +50,6 @@ ...@@ -50,9 +50,6 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/version.h> #include <linux/version.h>
#ifndef AHD_MODVERSION_FILE
#define __NO_VERSION__
#endif
#include <linux/module.h> #include <linux/module.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/io.h> #include <asm/io.h>
......
...@@ -119,12 +119,6 @@ ...@@ -119,12 +119,6 @@
* *
*/ */
/*
* This is the only file where module.h should
* embed module global version info.
*/
#define AHC_MODVERSION_FILE
#include "aic7xxx_osm.h" #include "aic7xxx_osm.h"
#include "aic7xxx_inline.h" #include "aic7xxx_inline.h"
#include <scsi/scsicam.h> #include <scsi/scsicam.h>
......
...@@ -67,9 +67,6 @@ ...@@ -67,9 +67,6 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/version.h> #include <linux/version.h>
#ifndef AHC_MODVERSION_FILE
#define __NO_VERSION__
#endif
#include <linux/module.h> #include <linux/module.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/io.h> #include <asm/io.h>
......
...@@ -20,10 +20,24 @@ ...@@ -20,10 +20,24 @@
} \ } \
\ \
/* Kernel symbol table: GPL-only symbols */ \ /* Kernel symbol table: GPL-only symbols */ \
__gpl_ksymtab : AT(ADDR(__gpl_ksymtab) - LOAD_OFFSET) { \ __ksymtab_gpl : AT(ADDR(__ksymtab_gpl) - LOAD_OFFSET) { \
__start___gpl_ksymtab = .; \ __start___ksymtab_gpl = .; \
*(__gpl_ksymtab) \ *(__ksymtab_gpl) \
__stop___gpl_ksymtab = .; \ __stop___ksymtab_gpl = .; \
} \
\
/* Kernel symbol table: Normal symbols */ \
__kcrctab : AT(ADDR(__kcrctab) - LOAD_OFFSET) { \
__start___kcrctab = .; \
*(__kcrctab) \
__stop___kcrctab = .; \
} \
\
/* Kernel symbol table: GPL-only symbols */ \
__kcrctab_gpl : AT(ADDR(__kcrctab_gpl) - LOAD_OFFSET) { \
__start___kcrctab_gpl = .; \
*(__kcrctab_gpl) \
__stop___kcrctab_gpl = .; \
} \ } \
\ \
/* Kernel symbol table: strings */ \ /* Kernel symbol table: strings */ \
......
...@@ -33,12 +33,19 @@ ...@@ -33,12 +33,19 @@
#endif #endif
#define MODULE_NAME_LEN (64 - sizeof(unsigned long)) #define MODULE_NAME_LEN (64 - sizeof(unsigned long))
struct kernel_symbol struct kernel_symbol
{ {
unsigned long value; unsigned long value;
const char *name; 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. */ /* These are either module local, or the kernel's dummy ones. */
extern int init_module(void); extern int init_module(void);
extern void cleanup_module(void); extern void cleanup_module(void);
...@@ -92,7 +99,7 @@ extern const struct gtype##_id __mod_##gtype##_table \ ...@@ -92,7 +99,7 @@ extern const struct gtype##_id __mod_##gtype##_table \
*/ */
#define MODULE_LICENSE(license) \ #define MODULE_LICENSE(license) \
static const char __module_license[] \ static const char __module_license[] \
__attribute__((section(".init.license"))) = license __attribute__((section(".init.license"), unused)) = license
#else /* !MODULE */ #else /* !MODULE */
...@@ -119,6 +126,7 @@ struct kernel_symbol_group ...@@ -119,6 +126,7 @@ struct kernel_symbol_group
unsigned int num_syms; unsigned int num_syms;
const struct kernel_symbol *syms; const struct kernel_symbol *syms;
const unsigned long *crcs;
}; };
/* Given an address, look for it in the exception tables */ /* Given an address, look for it in the exception tables */
...@@ -134,29 +142,52 @@ struct exception_table ...@@ -134,29 +142,52 @@ struct exception_table
#ifdef CONFIG_MODULES #ifdef CONFIG_MODULES
/* Get/put a kernel symbol (calls must be symmetric) */ /* Get/put a kernel symbol (calls must be symmetric) */
void *__symbol_get(const char *symbol); void *__symbol_get(const char *symbol);
void *__symbol_get_gpl(const char *symbol); void *__symbol_get_gpl(const char *symbol);
#define symbol_get(x) ((typeof(&x))(__symbol_get(MODULE_SYMBOL_PREFIX #x))) #define symbol_get(x) ((typeof(&x))(__symbol_get(MODULE_SYMBOL_PREFIX #x)))
#ifdef __GENKSYMS__
/* genksyms doesn't handle GPL-only symbols yet */
#define EXPORT_SYMBOL_GPL EXPORT_SYMBOL
#else
#ifdef CONFIG_MODVERSIONS
/* Mark the CRC weak since genksyms apparently decides not to
* generate a checksums for some symbols */
#define __CRC_SYMBOL(sym, sec) \
extern void *__crc_##sym __attribute__((weak)); \
static const unsigned long __kcrctab_##sym \
__attribute__((section("__kcrctab" sec), unused)) \
= (unsigned long) &__crc_##sym;
#else
#define __CRC_SYMBOL(sym, sec)
#endif
/* For every exported symbol, place a struct in the __ksymtab section */ /* For every exported symbol, place a struct in the __ksymtab section */
#define EXPORT_SYMBOL(sym) \ #define __EXPORT_SYMBOL(sym, sec) \
__CRC_SYMBOL(sym, sec) \
static const char __kstrtab_##sym[] \ static const char __kstrtab_##sym[] \
__attribute__((section("__ksymtab_strings"))) \ __attribute__((section("__ksymtab_strings"))) \
= MODULE_SYMBOL_PREFIX #sym; \ = MODULE_SYMBOL_PREFIX #sym; \
static const struct kernel_symbol __ksymtab_##sym \ static const struct kernel_symbol __ksymtab_##sym \
__attribute__((section("__ksymtab"))) \ __attribute__((section("__ksymtab" sec), unused)) \
= { (unsigned long)&sym, __kstrtab_##sym } = { (unsigned long)&sym, __kstrtab_##sym }
#define EXPORT_SYMBOL_NOVERS(sym) EXPORT_SYMBOL(sym) #define EXPORT_SYMBOL(sym) \
__EXPORT_SYMBOL(sym, "")
#define EXPORT_SYMBOL_GPL(sym) \ #define EXPORT_SYMBOL_GPL(sym) \
static const char __kstrtab_##sym[] \ __EXPORT_SYMBOL(sym, "_gpl")
__attribute__((section("__ksymtab_strings"))) \
= MODULE_SYMBOL_PREFIX #sym; \ #endif
static const struct kernel_symbol __ksymtab_##sym \
__attribute__((section("__gpl_ksymtab"))) \ /* We don't mangle the actual symbol anymore, so no need for
= { (unsigned long)&sym, __kstrtab_##sym } * special casing EXPORT_SYMBOL_NOVERS */
#define EXPORT_SYMBOL_NOVERS(sym) EXPORT_SYMBOL(sym)
struct module_ref struct module_ref
{ {
......
...@@ -144,6 +144,18 @@ config OBSOLETE_MODPARM ...@@ -144,6 +144,18 @@ config OBSOLETE_MODPARM
have not been converted to the new module parameter system yet. have not been converted to the new module parameter system yet.
If unsure, say Y. If unsure, say Y.
config MODVERSIONS
bool "Module versioning support (EXPERIMENTAL)"
depends on MODULES && EXPERIMENTAL
help
Usually, you have to use modules compiled with your kernel.
Saying Y here makes it sometimes possible to use modules
compiled for different kernels, by adding enough information
to the modules to (hopefully) spot any changes which would
make them incompatible with the kernel you are running. If
you say Y here, you will need a copy of genksyms. If
unsure, say N.
config KMOD config KMOD
bool "Kernel module loader" bool "Kernel module loader"
depends on MODULES depends on MODULES
......
...@@ -68,13 +68,6 @@ extern struct timezone sys_tz; ...@@ -68,13 +68,6 @@ extern struct timezone sys_tz;
extern int panic_timeout; extern int panic_timeout;
#ifdef CONFIG_MODVERSIONS
const struct module_symbol __export_Using_Versions
__attribute__((section("__ksymtab"))) = {
1 /* Version version */, "Using_Versions"
};
#endif
/* process memory management */ /* process memory management */
EXPORT_SYMBOL(do_mmap_pgoff); EXPORT_SYMBOL(do_mmap_pgoff);
EXPORT_SYMBOL(do_munmap); EXPORT_SYMBOL(do_munmap);
......
...@@ -78,6 +78,7 @@ EXPORT_SYMBOL(init_module); ...@@ -78,6 +78,7 @@ EXPORT_SYMBOL(init_module);
/* Find a symbol, return value and the symbol group */ /* Find a symbol, return value and the symbol group */
static unsigned long __find_symbol(const char *name, static unsigned long __find_symbol(const char *name,
struct kernel_symbol_group **group, struct kernel_symbol_group **group,
unsigned int *symidx,
int gplok) int gplok)
{ {
struct kernel_symbol_group *ks; struct kernel_symbol_group *ks;
...@@ -90,6 +91,8 @@ static unsigned long __find_symbol(const char *name, ...@@ -90,6 +91,8 @@ static unsigned long __find_symbol(const char *name,
for (i = 0; i < ks->num_syms; i++) { for (i = 0; i < ks->num_syms; i++) {
if (strcmp(ks->syms[i].name, name) == 0) { if (strcmp(ks->syms[i].name, name) == 0) {
*group = ks; *group = ks;
if (symidx)
*symidx = i;
return ks->syms[i].value; return ks->syms[i].value;
} }
} }
...@@ -520,7 +523,7 @@ void __symbol_put(const char *symbol) ...@@ -520,7 +523,7 @@ void __symbol_put(const char *symbol)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&modlist_lock, flags); spin_lock_irqsave(&modlist_lock, flags);
if (!__find_symbol(symbol, &ksg, 1)) if (!__find_symbol(symbol, &ksg, NULL, 1))
BUG(); BUG();
module_put(ksg->owner); module_put(ksg->owner);
spin_unlock_irqrestore(&modlist_lock, flags); spin_unlock_irqrestore(&modlist_lock, flags);
...@@ -722,22 +725,91 @@ static int obsolete_params(const char *name, ...@@ -722,22 +725,91 @@ static int obsolete_params(const char *name,
} }
#endif /* CONFIG_OBSOLETE_MODPARM */ #endif /* CONFIG_OBSOLETE_MODPARM */
#ifdef CONFIG_MODVERSIONS
static int check_version(Elf_Shdr *sechdrs,
unsigned int versindex,
const char *symname,
struct module *mod,
struct kernel_symbol_group *ksg,
unsigned int symidx)
{
unsigned long crc;
unsigned int i, num_versions;
struct modversion_info *versions;
/* Exporting module didn't supply crcs? OK, we're already tainted. */
if (!ksg->crcs)
return 1;
crc = ksg->crcs[symidx];
versions = (void *) sechdrs[versindex].sh_addr;
num_versions = sechdrs[versindex].sh_size
/ sizeof(struct modversion_info);
for (i = 0; i < num_versions; i++) {
if (strcmp(versions[i].name, symname) != 0)
continue;
if (versions[i].crc == crc)
return 1;
printk("%s: disagrees about version of symbol %s\n",
mod->name, symname);
DEBUGP("Found checksum %lX vs module %lX\n",
crc, versions[i].crc);
return 0;
}
/* Not in module's version table. OK, but that taints the kernel. */
if (!(tainted & TAINT_FORCED_MODULE)) {
printk("%s: no version for \"%s\" found: kernel tainted.\n",
mod->name, symname);
tainted |= TAINT_FORCED_MODULE;
}
return 1;
}
/* First part is kernel version, which we ignore. */
static inline int same_magic(const char *amagic, const char *bmagic)
{
amagic += strcspn(amagic, " ");
bmagic += strcspn(bmagic, " ");
return strcmp(amagic, bmagic) == 0;
}
#else
static inline int check_version(Elf_Shdr *sechdrs,
unsigned int versindex,
const char *symname,
struct module *mod,
struct kernel_symbol_group *ksg,
unsigned int symidx)
{
return 1;
}
static inline int same_magic(const char *amagic, const char *bmagic)
{
return strcmp(amagic, bmagic) == 0;
}
#endif /* CONFIG_MODVERSIONS */
/* Resolve a symbol for this module. I.e. if we find one, record usage. /* Resolve a symbol for this module. I.e. if we find one, record usage.
Must be holding module_mutex. */ Must be holding module_mutex. */
static unsigned long resolve_symbol(Elf_Shdr *sechdrs, static unsigned long resolve_symbol(Elf_Shdr *sechdrs,
unsigned int symindex, unsigned int versindex,
const char *strtab,
const char *name, const char *name,
struct module *mod) struct module *mod)
{ {
struct kernel_symbol_group *ksg; struct kernel_symbol_group *ksg;
unsigned long ret; unsigned long ret;
unsigned int symidx;
spin_lock_irq(&modlist_lock); spin_lock_irq(&modlist_lock);
ret = __find_symbol(name, &ksg, mod->license_gplok); ret = __find_symbol(name, &ksg, &symidx, mod->license_gplok);
if (ret) { if (ret) {
/* This can fail due to OOM, or module unloading */ /* use_module can fail due to OOM, or module unloading */
if (!use_module(mod, ksg->owner)) if (!check_version(sechdrs, versindex, name, mod,
ksg, symidx) ||
!use_module(mod, ksg->owner))
ret = 0; ret = 0;
} }
spin_unlock_irq(&modlist_lock); spin_unlock_irq(&modlist_lock);
...@@ -772,7 +844,7 @@ void *__symbol_get(const char *symbol) ...@@ -772,7 +844,7 @@ void *__symbol_get(const char *symbol)
unsigned long value, flags; unsigned long value, flags;
spin_lock_irqsave(&modlist_lock, flags); spin_lock_irqsave(&modlist_lock, flags);
value = __find_symbol(symbol, &ksg, 1); value = __find_symbol(symbol, &ksg, NULL, 1);
if (value && !strong_try_module_get(ksg->owner)) if (value && !strong_try_module_get(ksg->owner))
value = 0; value = 0;
spin_unlock_irqrestore(&modlist_lock, flags); spin_unlock_irqrestore(&modlist_lock, flags);
...@@ -824,6 +896,7 @@ static int handle_section(const char *name, ...@@ -824,6 +896,7 @@ static int handle_section(const char *name,
static int simplify_symbols(Elf_Shdr *sechdrs, static int simplify_symbols(Elf_Shdr *sechdrs,
unsigned int symindex, unsigned int symindex,
unsigned int strindex, unsigned int strindex,
unsigned int versindex,
struct module *mod) struct module *mod)
{ {
Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr; Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr;
...@@ -848,7 +921,7 @@ static int simplify_symbols(Elf_Shdr *sechdrs, ...@@ -848,7 +921,7 @@ static int simplify_symbols(Elf_Shdr *sechdrs,
case SHN_UNDEF: case SHN_UNDEF:
sym[i].st_value sym[i].st_value
= resolve_symbol(sechdrs, symindex, strtab, = resolve_symbol(sechdrs, versindex,
strtab + sym[i].st_name, mod); strtab + sym[i].st_name, mod);
/* Ok if resolved. */ /* Ok if resolved. */
...@@ -916,7 +989,7 @@ static void layout_sections(struct module *mod, ...@@ -916,7 +989,7 @@ static void layout_sections(struct module *mod,
|| strstr(secstrings + s->sh_name, ".init")) || strstr(secstrings + s->sh_name, ".init"))
continue; continue;
s->sh_entsize = get_offset(&mod->core_size, s); s->sh_entsize = get_offset(&mod->core_size, s);
DEBUGP("\t%s\n", name); DEBUGP("\t%s\n", secstrings + s->sh_name);
} }
} }
...@@ -932,7 +1005,7 @@ static void layout_sections(struct module *mod, ...@@ -932,7 +1005,7 @@ static void layout_sections(struct module *mod,
continue; continue;
s->sh_entsize = (get_offset(&mod->init_size, s) s->sh_entsize = (get_offset(&mod->init_size, s)
| INIT_OFFSET_MASK); | INIT_OFFSET_MASK);
DEBUGP("\t%s\n", name); DEBUGP("\t%s\n", secstrings + s->sh_name);
} }
} }
} }
...@@ -976,7 +1049,8 @@ static struct module *load_module(void *umod, ...@@ -976,7 +1049,8 @@ static struct module *load_module(void *umod,
Elf_Shdr *sechdrs; Elf_Shdr *sechdrs;
char *secstrings, *args; char *secstrings, *args;
unsigned int i, symindex, exportindex, strindex, setupindex, exindex, unsigned int i, symindex, exportindex, strindex, setupindex, exindex,
modindex, obsparmindex, licenseindex, gplindex, vmagindex; modindex, obsparmindex, licenseindex, gplindex, vmagindex,
crcindex, gplcrcindex, versindex;
long arglen; long arglen;
struct module *mod; struct module *mod;
long err = 0; long err = 0;
...@@ -1012,7 +1086,8 @@ static struct module *load_module(void *umod, ...@@ -1012,7 +1086,8 @@ static struct module *load_module(void *umod,
/* May not export symbols, or have setup params, so these may /* May not export symbols, or have setup params, so these may
not exist */ not exist */
exportindex = setupindex = obsparmindex = gplindex = licenseindex = 0; exportindex = setupindex = obsparmindex = gplindex = licenseindex
= crcindex = gplcrcindex = versindex = 0;
/* And these should exist, but gcc whinges if we don't init them */ /* And these should exist, but gcc whinges if we don't init them */
symindex = strindex = exindex = modindex = vmagindex = 0; symindex = strindex = exindex = modindex = vmagindex = 0;
...@@ -1040,6 +1115,21 @@ static struct module *load_module(void *umod, ...@@ -1040,6 +1115,21 @@ static struct module *load_module(void *umod,
/* Exported symbols. */ /* Exported symbols. */
DEBUGP("EXPORT table in section %u\n", i); DEBUGP("EXPORT table in section %u\n", i);
exportindex = i; exportindex = i;
} else if (strcmp(secstrings+sechdrs[i].sh_name,
"__ksymtab_gpl") == 0) {
/* Exported symbols. (GPL) */
DEBUGP("GPL symbols found in section %u\n", i);
gplindex = i;
} else if (strcmp(secstrings+sechdrs[i].sh_name, "__kcrctab")
== 0) {
/* Exported symbols CRCs. */
DEBUGP("CRC table in section %u\n", i);
crcindex = i;
} else if (strcmp(secstrings+sechdrs[i].sh_name, "__kcrctab_gpl")
== 0) {
/* Exported symbols CRCs. (GPL)*/
DEBUGP("CRC table in section %u\n", i);
gplcrcindex = i;
} else if (strcmp(secstrings+sechdrs[i].sh_name, "__param") } else if (strcmp(secstrings+sechdrs[i].sh_name, "__param")
== 0) { == 0) {
/* Setup parameter info */ /* Setup parameter info */
...@@ -1060,16 +1150,21 @@ static struct module *load_module(void *umod, ...@@ -1060,16 +1150,21 @@ static struct module *load_module(void *umod,
/* MODULE_LICENSE() */ /* MODULE_LICENSE() */
DEBUGP("Licence found in section %u\n", i); DEBUGP("Licence found in section %u\n", i);
licenseindex = i; licenseindex = i;
sechdrs[i].sh_flags &= ~(unsigned long)SHF_ALLOC;
} else if (strcmp(secstrings+sechdrs[i].sh_name, } else if (strcmp(secstrings+sechdrs[i].sh_name,
"__gpl_ksymtab") == 0) { "__vermagic") == 0 &&
/* EXPORT_SYMBOL_GPL() */ (sechdrs[i].sh_flags & SHF_ALLOC)) {
DEBUGP("GPL symbols found in section %u\n", i);
gplindex = i;
} else if (strcmp(secstrings+sechdrs[i].sh_name,
"__vermagic") == 0) {
/* Version magic. */ /* Version magic. */
DEBUGP("Version magic found in section %u\n", i); DEBUGP("Version magic found in section %u\n", i);
vmagindex = i; vmagindex = i;
sechdrs[i].sh_flags &= ~(unsigned long)SHF_ALLOC;
} else if (strcmp(secstrings+sechdrs[i].sh_name,
"__versions") == 0 &&
(sechdrs[i].sh_flags & SHF_ALLOC)) {
/* Module version info (both exported and needed) */
DEBUGP("Versions found in section %u\n", i);
versindex = i;
sechdrs[i].sh_flags &= ~(unsigned long)SHF_ALLOC;
} }
#ifdef CONFIG_KALLSYMS #ifdef CONFIG_KALLSYMS
/* symbol and string tables for decoding later. */ /* symbol and string tables for decoding later. */
...@@ -1090,12 +1185,12 @@ static struct module *load_module(void *umod, ...@@ -1090,12 +1185,12 @@ static struct module *load_module(void *umod,
} }
mod = (void *)sechdrs[modindex].sh_addr; mod = (void *)sechdrs[modindex].sh_addr;
/* This is allowed: modprobe --force will strip it. */ /* This is allowed: modprobe --force will invalidate it. */
if (!vmagindex) { if (!vmagindex) {
tainted |= TAINT_FORCED_MODULE; tainted |= TAINT_FORCED_MODULE;
printk(KERN_WARNING "%s: no version magic, tainting kernel.\n", printk(KERN_WARNING "%s: no version magic, tainting kernel.\n",
mod->name); mod->name);
} else if (strcmp((char *)sechdrs[vmagindex].sh_addr, vermagic) != 0) { } else if (!same_magic((char *)sechdrs[vmagindex].sh_addr, vermagic)) {
printk(KERN_ERR "%s: version magic '%s' should be '%s'\n", printk(KERN_ERR "%s: version magic '%s' should be '%s'\n",
mod->name, (char*)sechdrs[vmagindex].sh_addr, vermagic); mod->name, (char*)sechdrs[vmagindex].sh_addr, vermagic);
err = -ENOEXEC; err = -ENOEXEC;
...@@ -1181,7 +1276,7 @@ static struct module *load_module(void *umod, ...@@ -1181,7 +1276,7 @@ static struct module *load_module(void *umod,
set_license(mod, sechdrs, licenseindex); set_license(mod, sechdrs, licenseindex);
/* Fix up syms, so that st_value is a pointer to location. */ /* Fix up syms, so that st_value is a pointer to location. */
err = simplify_symbols(sechdrs, symindex, strindex, mod); err = simplify_symbols(sechdrs, symindex, strindex, versindex, mod);
if (err < 0) if (err < 0)
goto cleanup; goto cleanup;
...@@ -1189,9 +1284,23 @@ static struct module *load_module(void *umod, ...@@ -1189,9 +1284,23 @@ static struct module *load_module(void *umod,
mod->symbols.num_syms = (sechdrs[exportindex].sh_size mod->symbols.num_syms = (sechdrs[exportindex].sh_size
/ sizeof(*mod->symbols.syms)); / sizeof(*mod->symbols.syms));
mod->symbols.syms = (void *)sechdrs[exportindex].sh_addr; mod->symbols.syms = (void *)sechdrs[exportindex].sh_addr;
if (crcindex)
mod->symbols.crcs = (void *)sechdrs[crcindex].sh_addr;
mod->gpl_symbols.num_syms = (sechdrs[gplindex].sh_size mod->gpl_symbols.num_syms = (sechdrs[gplindex].sh_size
/ sizeof(*mod->symbols.syms)); / sizeof(*mod->symbols.syms));
mod->gpl_symbols.syms = (void *)sechdrs[gplindex].sh_addr; mod->gpl_symbols.syms = (void *)sechdrs[gplindex].sh_addr;
if (gplcrcindex)
mod->gpl_symbols.crcs = (void *)sechdrs[gplcrcindex].sh_addr;
#ifdef CONFIG_MODVERSIONS
if ((mod->symbols.num_syms && !crcindex)
|| (mod->gpl_symbols.num_syms && !gplcrcindex))
printk(KERN_WARNING "%s: No versions for exported symbols."
" Tainting kernel.\n", mod->name);
tainted |= TAINT_FORCED_MODULE;
}
#endif
/* Set up exception table */ /* Set up exception table */
if (exindex) { if (exindex) {
...@@ -1492,8 +1601,12 @@ int module_text_address(unsigned long addr) ...@@ -1492,8 +1601,12 @@ int module_text_address(unsigned long addr)
/* Provided by the linker */ /* Provided by the linker */
extern const struct kernel_symbol __start___ksymtab[]; extern const struct kernel_symbol __start___ksymtab[];
extern const struct kernel_symbol __stop___ksymtab[]; extern const struct kernel_symbol __stop___ksymtab[];
extern const struct kernel_symbol __start___gpl_ksymtab[]; extern const struct kernel_symbol __start___ksymtab_gpl[];
extern const struct kernel_symbol __stop___gpl_ksymtab[]; extern const struct kernel_symbol __stop___ksymtab_gpl[];
extern const unsigned long __start___kcrctab[];
extern const unsigned long __stop___kcrctab[];
extern const unsigned long __start___kcrctab_gpl[];
extern const unsigned long __stop___kcrctab_gpl[];
static struct kernel_symbol_group kernel_symbols, kernel_gpl_symbols; static struct kernel_symbol_group kernel_symbols, kernel_gpl_symbols;
...@@ -1502,11 +1615,14 @@ static int __init symbols_init(void) ...@@ -1502,11 +1615,14 @@ static int __init symbols_init(void)
/* Add kernel symbols to symbol table */ /* Add kernel symbols to symbol table */
kernel_symbols.num_syms = (__stop___ksymtab - __start___ksymtab); kernel_symbols.num_syms = (__stop___ksymtab - __start___ksymtab);
kernel_symbols.syms = __start___ksymtab; kernel_symbols.syms = __start___ksymtab;
kernel_symbols.crcs = __start___kcrctab;
kernel_symbols.gplonly = 0; kernel_symbols.gplonly = 0;
list_add(&kernel_symbols.list, &symbols); list_add(&kernel_symbols.list, &symbols);
kernel_gpl_symbols.num_syms = (__stop___gpl_ksymtab
- __start___gpl_ksymtab); kernel_gpl_symbols.num_syms = (__stop___ksymtab_gpl
kernel_gpl_symbols.syms = __start___gpl_ksymtab; - __start___ksymtab_gpl);
kernel_gpl_symbols.syms = __start___ksymtab_gpl;
kernel_gpl_symbols.crcs = __start___kcrctab_gpl;
kernel_gpl_symbols.gplonly = 1; kernel_gpl_symbols.gplonly = 1;
list_add(&kernel_gpl_symbols.list, &symbols); list_add(&kernel_gpl_symbols.list, &symbols);
......
...@@ -45,11 +45,67 @@ O_TARGET := $(obj)/built-in.o ...@@ -45,11 +45,67 @@ O_TARGET := $(obj)/built-in.o
endif endif
endif endif
ifdef CONFIG_MODVERSIONS
modules := $(obj-m)
touch-module = @mkdir -p $(MODVERDIR)/$(@D); touch $(MODVERDIR)/$(@:.o=.ko)
else
modules := $(obj-m:.o=.ko)
endif
__build: $(if $(KBUILD_BUILTIN),$(O_TARGET) $(L_TARGET) $(EXTRA_TARGETS)) \ __build: $(if $(KBUILD_BUILTIN),$(O_TARGET) $(L_TARGET) $(EXTRA_TARGETS)) \
$(if $(KBUILD_MODULES),$(obj-m:.o=.ko)) \ $(if $(KBUILD_MODULES),$(modules)) \
$(subdir-ym) $(build-targets) $(subdir-ym) $(build-targets)
@: @:
# Module versioning
# ---------------------------------------------------------------------------
ifdef CONFIG_MODVERSIONS
# $(call if_changed_rule,vcc_o_c) does essentially the same as the
# normal $(call if_changed_dep,cc_o_c), i.e. compile an object file
# from a C file, keeping track of the command line and dependencies.
#
# However, actually it does:
# o compile a .tmp_<file>.o from <file>.c
# o if .tmp_<file>.o doesn't contain a __ksymtab version, i.e. does
# not export symbols, we just rename .tmp_<file>.o to <file>.o and
# are done.
# o otherwise, we calculate symbol versions using the good old
# genksyms on the preprocessed source and postprocess them in a way
# that they are usable as a linker script
# o generate <file>.o from .tmp_<file>.o using the linker to
# replace the unresolved symbols __crc_exported_symbol with
# the actual value of the checksum generated by genksyms
quiet_cmd_vcc_o_c = CC $(quiet_modtag) $@
cmd_vcc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $<
define rule_vcc_o_c
$(if $($(quiet)cmd_vcc_o_c),echo ' $($(quiet)cmd_vcc_o_c)';) \
$(cmd_vcc_o_c); \
\
if ! $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \
mv $(@D)/.tmp_$(@F) $@; \
else \
$(CPP) -D__GENKSYMS__ $(c_flags) $< \
| $(GENKSYMS) -k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) \
| grep __ver \
| sed 's/\#define __ver_\([^ ]*\)[ ]*\([^ ]*\)/__crc_\1 = 0x\2 ;/g' \
> $(@D)/.tmp_$(@F:.o=.ver); \
\
$(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \
-T $(@D)/.tmp_$(@F:.o=.ver); \
rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver); \
fi;
\
scripts/fixdep $(depfile) $@ '$(cmd_vcc_o_c)' > $(@D)/.$(@F).tmp; \
rm -f $(depfile); \
mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd
endef
endif
# Compile C sources (.c) # Compile C sources (.c)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
...@@ -69,11 +125,6 @@ $(real-objs-m:.o=.lst): quiet_modtag := [M] ...@@ -69,11 +125,6 @@ $(real-objs-m:.o=.lst): quiet_modtag := [M]
$(obj-m) : quiet_modtag := [M] $(obj-m) : quiet_modtag := [M]
$(export-objs) : export_flags := $(EXPORT_FLAGS)
$(export-objs:.o=.i) : export_flags := $(EXPORT_FLAGS)
$(export-objs:.o=.s) : export_flags := $(EXPORT_FLAGS)
$(export-objs:.o=.lst): export_flags := $(EXPORT_FLAGS)
# Default for not multi-part modules # Default for not multi-part modules
modname = $(*F) modname = $(*F)
...@@ -102,7 +153,20 @@ quiet_cmd_cc_o_c = CC $(quiet_modtag) $@ ...@@ -102,7 +153,20 @@ quiet_cmd_cc_o_c = CC $(quiet_modtag) $@
cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
%.o: %.c FORCE %.o: %.c FORCE
ifdef CONFIG_MODVERSIONS
$(call if_changed_rule,vcc_o_c)
else
$(call if_changed_dep,cc_o_c) $(call if_changed_dep,cc_o_c)
endif
# For modversioning, we need to special case single-part modules
# to mark them in $(MODVERDIR)
ifdef CONFIG_MODVERSIONS
$(single-used-m): %.o: %.c FORCE
$(touch-module)
$(call if_changed_rule,vcc_o_c)
endif
quiet_cmd_cc_lst_c = MKLST $@ quiet_cmd_cc_lst_c = MKLST $@
cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \ cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \
...@@ -176,15 +240,7 @@ quiet_cmd_link_multi-y = LD $@ ...@@ -176,15 +240,7 @@ quiet_cmd_link_multi-y = LD $@
cmd_link_multi-y = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) -r -o $@ $(filter $(addprefix $(obj)/,$($(subst $(obj)/,,$(@:.o=-objs))) $($(subst $(obj)/,,$(@:.o=-y)))),$^) cmd_link_multi-y = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) -r -o $@ $(filter $(addprefix $(obj)/,$($(subst $(obj)/,,$(@:.o=-objs))) $($(subst $(obj)/,,$(@:.o=-y)))),$^)
quiet_cmd_link_multi-m = LD [M] $@ quiet_cmd_link_multi-m = LD [M] $@
cmd_link_multi-m = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_MODULE) -o $@ $(filter $(addprefix $(obj)/,$($(subst $(obj)/,,$(@:.ko=-objs))) $($(subst $(obj)/,,$(@:.ko=-y)))),$^) init/vermagic.o cmd_link_multi-m = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_MODULE) -o $@ $(filter $(addprefix $(obj)/,$($(subst $(obj)/,,$(@:.o=-objs))) $($(subst $(obj)/,,$(@:.o=-y)))),$^)
quiet_cmd_link_single-m = LD [M] $@
cmd_link_single-m = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_MODULE) -o $@ $< init/vermagic.o
# Don't rebuilt vermagic.o unless we actually are in the init/ dir
ifneq ($(obj),init)
init/vermagic.o: ;
endif
# We would rather have a list of rules like # We would rather have a list of rules like
# foo.o: $(foo-objs) # foo.o: $(foo-objs)
...@@ -193,13 +249,34 @@ endif ...@@ -193,13 +249,34 @@ endif
$(multi-used-y) : %.o: $(multi-objs-y) FORCE $(multi-used-y) : %.o: $(multi-objs-y) FORCE
$(call if_changed,link_multi-y) $(call if_changed,link_multi-y)
$(multi-used-m:.o=.ko) : %.ko: $(multi-objs-m) init/vermagic.o FORCE $(multi-used-m) : %.o: $(multi-objs-m) FORCE
$(touch-module)
$(call if_changed,link_multi-m) $(call if_changed,link_multi-m)
$(single-used-m:.o=.ko) : %.ko: %.o init/vermagic.o FORCE targets += $(multi-used-y) $(multi-used-m)
$(call if_changed,link_single-m)
#
# Rule to link modules ( .o -> .ko )
#
# With CONFIG_MODVERSIONS, generation of the final .ko is handled
# by scripts/Makefile.modver
ifndef CONFIG_MODVERSIONS
quiet_cmd_link_module = LD [M] $@
cmd_link_module = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_MODULE) -o $@ $< init/vermagic.o
targets += $(multi-used-y) $(multi-used-m:.o=.ko) $(single-used-m:.o=.ko) # Don't rebuilt vermagic.o unless we actually are in the init/ dir
ifneq ($(obj),init)
init/vermagic.o: ;
endif
$(single-used-m:.o=.ko) $(multi-used-m:.o=.ko): %.ko: %.o init/vermagic.o FORCE
$(call if_changed,link_module)
targets += $(single-used-m:.o=.ko) $(multi-used-m:.o=.ko)
endif
# Compile programs on the host # Compile programs on the host
# =========================================================================== # ===========================================================================
......
...@@ -34,14 +34,9 @@ obj-m := $(filter-out %/, $(obj-m)) ...@@ -34,14 +34,9 @@ obj-m := $(filter-out %/, $(obj-m))
subdir-ym := $(sort $(subdir-y) $(subdir-m)) subdir-ym := $(sort $(subdir-y) $(subdir-m))
# export.o is never a composite object, since $(export-objs) has a
# fixed meaning (== objects which EXPORT_SYMBOL())
__obj-y = $(filter-out export.o,$(obj-y))
__obj-m = $(filter-out export.o,$(obj-m))
# if $(foo-objs) exists, foo.o is a composite object # if $(foo-objs) exists, foo.o is a composite object
multi-used-y := $(sort $(foreach m,$(__obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m)))) multi-used-y := $(sort $(foreach m,$(obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m))))
multi-used-m := $(sort $(foreach m,$(__obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m)))) multi-used-m := $(sort $(foreach m,$(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m))))
multi-used := $(multi-used-y) $(multi-used-m) multi-used := $(multi-used-y) $(multi-used-m)
single-used-m := $(sort $(filter-out $(multi-used-m),$(obj-m))) single-used-m := $(sort $(filter-out $(multi-used-m),$(obj-m)))
...@@ -59,9 +54,6 @@ subdir-obj-y := $(foreach o,$(obj-y),$(if $(filter-out $(o),$(notdir $(o))),$(o) ...@@ -59,9 +54,6 @@ subdir-obj-y := $(foreach o,$(obj-y),$(if $(filter-out $(o),$(notdir $(o))),$(o)
real-objs-y := $(foreach m, $(filter-out $(subdir-obj-y), $(obj-y)), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) $(EXTRA_TARGETS) real-objs-y := $(foreach m, $(filter-out $(subdir-obj-y), $(obj-y)), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) $(EXTRA_TARGETS)
real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m)))
# Only build module versions for files which are selected to be built
export-objs := $(filter $(export-objs),$(real-objs-y) $(real-objs-m))
# C code # C code
# Executables compiled from a single .c file # Executables compiled from a single .c file
host-csingle := $(foreach m,$(host-progs),$(if $($(m)-objs),,$(m))) host-csingle := $(foreach m,$(host-progs),$(if $($(m)-objs),,$(m)))
...@@ -96,7 +88,6 @@ EXTRA_TARGETS := $(addprefix $(obj)/,$(EXTRA_TARGETS)) ...@@ -96,7 +88,6 @@ EXTRA_TARGETS := $(addprefix $(obj)/,$(EXTRA_TARGETS))
build-targets := $(addprefix $(obj)/,$(build-targets)) build-targets := $(addprefix $(obj)/,$(build-targets))
obj-y := $(addprefix $(obj)/,$(obj-y)) obj-y := $(addprefix $(obj)/,$(obj-y))
obj-m := $(addprefix $(obj)/,$(obj-m)) obj-m := $(addprefix $(obj)/,$(obj-m))
export-objs := $(addprefix $(obj)/,$(export-objs))
subdir-obj-y := $(addprefix $(obj)/,$(subdir-obj-y)) subdir-obj-y := $(addprefix $(obj)/,$(subdir-obj-y))
real-objs-y := $(addprefix $(obj)/,$(real-objs-y)) real-objs-y := $(addprefix $(obj)/,$(real-objs-y))
real-objs-m := $(addprefix $(obj)/,$(real-objs-m)) real-objs-m := $(addprefix $(obj)/,$(real-objs-m))
...@@ -130,7 +121,7 @@ basename_flags = -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) ...@@ -130,7 +121,7 @@ basename_flags = -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F)))
modname_flags = $(if $(filter 1,$(words $(modname))),-DKBUILD_MODNAME=$(subst $(comma),_,$(subst -,_,$(modname)))) modname_flags = $(if $(filter 1,$(words $(modname))),-DKBUILD_MODNAME=$(subst $(comma),_,$(subst -,_,$(modname))))
c_flags = -Wp,-MD,$(depfile) $(CFLAGS) $(NOSTDINC_FLAGS) \ c_flags = -Wp,-MD,$(depfile) $(CFLAGS) $(NOSTDINC_FLAGS) \
$(modkern_cflags) $(EXTRA_CFLAGS) $(CFLAGS_$(*F).o) \ $(modkern_cflags) $(EXTRA_CFLAGS) $(CFLAGS_$(*F).o) \
$(basename_flags) $(modname_flags) $(export_flags) $(basename_flags) $(modname_flags)
a_flags = -Wp,-MD,$(depfile) $(AFLAGS) $(NOSTDINC_FLAGS)\ a_flags = -Wp,-MD,$(depfile) $(AFLAGS) $(NOSTDINC_FLAGS)\
$(modkern_aflags) $(EXTRA_AFLAGS) $(AFLAGS_$(*F).o) $(modkern_aflags) $(EXTRA_AFLAGS) $(AFLAGS_$(*F).o)
hostc_flags = -Wp,-MD,$(depfile) $(HOSTCFLAGS) $(HOST_EXTRACFLAGS)\ hostc_flags = -Wp,-MD,$(depfile) $(HOSTCFLAGS) $(HOST_EXTRACFLAGS)\
...@@ -217,7 +208,6 @@ if_changed_rule = $(if $(strip $? \ ...@@ -217,7 +208,6 @@ if_changed_rule = $(if $(strip $? \
$(filter-out $(cmd_$(1)),$(cmd_$@))\ $(filter-out $(cmd_$(1)),$(cmd_$@))\
$(filter-out $(cmd_$@),$(cmd_$(1)))),\ $(filter-out $(cmd_$@),$(cmd_$(1)))),\
@set -e; \ @set -e; \
mkdir -p $(dir $@); \
$(rule_$(1))) $(rule_$(1)))
# If quiet is set, only print short version of command # If quiet is set, only print short version of command
......
...@@ -2,105 +2,82 @@ ...@@ -2,105 +2,82 @@
# Module versions # Module versions
# =========================================================================== # ===========================================================================
src := $(obj) .PHONY: __modversions
__modversions:
MODVERDIR := include/linux/modules include scripts/Makefile.lib
.PHONY: modver #
modver:
include .config modules := $(patsubst ./%,%,$(shell cd $(MODVERDIR); find . -name \*.ko))
include $(obj)/Makefile __modversions: $(modules)
@:
include scripts/Makefile.lib # The final module link
# =========================================================================== quiet_cmd_ld_ko_o = LD [M] $@
cmd_ld_ko_o = $(LD) $(LDFLAGS) $(LDFLAGS_MODULE) -o $@ \
$(filter-out FORCE,$^)
ifeq ($(strip $(export-objs)),) init/vermagic.o: ;
# If we don't export any symbols in this dir, just descend $(modules): %.ko :%.o %.ver.o init/vermagic.o FORCE
# --------------------------------------------------------------------------- $(call if_changed,ld_ko_o)
modver: $(subdir-ym) targets += $(modules)
@:
else # Compile version info for unresolved symbols
# This sets version suffixes on exported symbols quiet_cmd_cc_o_c = CC $@
# --------------------------------------------------------------------------- cmd_cc_o_c = $(CC) $(CFLAGS) -c -o $@ $<
# $(modules:.ko=.ver.o): %.ver.o: %.ver.c FORCE
# Added the SMP separator to stop module accidents between uniprocessor $(call if_changed,cc_o_c)
# and SMP Intel boxes - AC - from bits by Michael Chastain
#
ifdef CONFIG_SMP targets += $(modules:.ko=.ver.o)
genksyms_smp_prefix := -p smp_
else # Generate C source with version info for unresolved symbols
genksyms_smp_prefix :=
endif
# Don't include modversions.h, we're just about to generate it here. define rule_mkver_o_c
echo ' MKVER $@'; \
CFLAGS_MODULE := $(filter-out -include include/linux/modversions.h,$(CFLAGS_MODULE)) ( echo "#include <linux/module.h>"; \
echo ""; \
$(addprefix $(MODVERDIR)/,$(real-objs-y:.o=.ver)): modkern_cflags := $(CFLAGS_KERNEL) echo "static const struct modversion_info ____versions[]"; \
$(addprefix $(MODVERDIR)/,$(real-objs-m:.o=.ver)): modkern_cflags := $(CFLAGS_MODULE) echo "__attribute__((section(\"__versions\"))) = {"; \
$(addprefix $(MODVERDIR)/,$(export-objs:.o=.ver)): export_flags := -D__GENKSYMS__ for sym in `nm -u $<`; do \
# Default for not multi-part modules grep "\"$$sym\"" .tmp_all-versions \
modname = $(*F) || echo "*** Warning: $(<:.o=.ko): \"$$sym\" unresolved!" >&2;\
done; \
$(addprefix $(MODVERDIR)/,$(multi-objs:.o=.ver)) : modname = $(modname-multi) echo "};"; \
) > $@
# Our objects only depend on modversions.h, not on the individual .ver
# files (fix-dep filters them), so touch modversions.h if any of the .ver
# files changes
quiet_cmd_cc_ver_c = MKVER include/linux/modules/$*.ver
cmd_cc_ver_c = $(CPP) $(c_flags) $< | $(GENKSYMS) $(genksyms_smp_prefix) \
-k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) > $@.tmp
# Okay, let's explain what's happening in rule_make_cc_ver_c:
# o echo the command
# o execute the command
# o If the $(CPP) fails, we won't notice because it's output is piped
# to $(GENKSYMS) which does not fail. We recognize this case by
# looking if the generated $(depfile) exists, though.
# o If the .ver file changed, touch modversions.h, which is our marker
# of any changed .ver files.
# o Move command line and deps into their normal .*.cmd place.
define rule_cc_ver_c
$(if $($(quiet)cmd_cc_ver_c),echo ' $($(quiet)cmd_cc_ver_c)';) \
$(cmd_cc_ver_c); \
if [ ! -r $(depfile) ]; then exit 1; fi; \
scripts/fixdep $(depfile) $@ '$(cmd_cc_ver_c)' > $(@D)/.$(@F).tmp; \
rm -f $(depfile); \
if [ ! -r $@ ] || cmp -s $@ $@.tmp; then \
touch include/linux/modversions.h; \
fi; \
mv -f $@.tmp $@
mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd
endef endef
targets := $(addprefix $(MODVERDIR)/,$(export-objs:.o=.ver)) $(modules:.ko=.ver.c): %.ver.c: %.o .tmp_all-versions FORCE
$(call if_changed_rule,mkver_o_c)
$(MODVERDIR)/%.ver: %.c FORCE targets += $(modules:.ko=.ver.c))
@$(call if_changed_rule,cc_ver_c)
modver: $(targets) $(subdir-ym) # Extract all checksums for all exported symbols
@mkdir -p $(dir $(addprefix .tmp_export-objs/modules/,$(export-objs:.o=.ver)))
@touch $(addprefix .tmp_export-objs/modules/,$(export-objs:.o=.ver))
endif # export-objs export-objs := $(shell for m in vmlinux $(modules:.ko=.o); do objdump -h $$m | grep -q __ksymtab && echo $$m; done)
# Descending 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)
.PHONY: $(subdir-ym) targets += .tmp_all-versions
$(subdir-ym):
$(Q)$(MAKE) -f scripts/Makefile.modver obj=$@
# Add FORCE to the prequisites of a target to force it to be always rebuilt. # Add FORCE to the prequisites of a target to force it to be always rebuilt.
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
IN_PER_CPU=0 IN_PER_CPU=0
} }
/__per_cpu$$/ && ! ( / __ksymtab_/ || / __kstrtab_/ ) { /__per_cpu$$/ && ! ( / __ksymtab_/ || / __kstrtab_/ || / __kcrctab_/ ) {
if (!IN_PER_CPU) { if (!IN_PER_CPU) {
print $$3 " not in per-cpu section" > "/dev/stderr"; print $$3 " not in per-cpu section" > "/dev/stderr";
FOUND=1; FOUND=1;
......
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