Commit 07e58231 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] kbuild: external module support

From: Sam Ravnborg <sam@ravnborg.org>

Based on initial patch from Andreas Gruenbacher there is now better support
for building external modules with kbuild.

The preferred syntax is now:
make -C $KERNELSRC M=$PWD

but the old syntax:
make -C $KERNELSRC SUBDIRS=$PWD modules
will remain supported.

The major differences compared to before are that:
1) No attempt is made to neither check nor update any files in $KERNELSRC
2) Module versions are now supported

During stage 2 of kernel compilation where the modules are built, a new file
Module.symvers is created.  This file contains the version for all symbols
exported by the kernel and any module compiled within the kernel tree.

When the external module is build the Module.symvers file is being read and
symbol versions are used from that file.

The purpose of avoiding any updates in the kernel src is that usually in a
distribution the kernel src will be read-only, and there is no need to try to
update it.  And when building an external module the focus is on the module,
not the kernel.

I expect the distributions will start using something like this:

kernel src - with no generated files. Not even .config:
/usr/src/linux-<version>

Output from build:
/lib/modules/linux-<version>/build

where build is a real directory with relevant output files and the
appropriate .config.

I have some Documentation in the pipe-line, but wants to see how this
approach is received before completing it.

This patch is made on top of the previously posted patch to divide
make clean in three steps.

And you may need to edit the following line in the patch to make it apply:
 %docs: scripts_basic FORCE
to
 %docs: scripts FORCE
parent a065cde3
...@@ -53,6 +53,19 @@ ifndef KBUILD_CHECKSRC ...@@ -53,6 +53,19 @@ ifndef KBUILD_CHECKSRC
KBUILD_CHECKSRC = 0 KBUILD_CHECKSRC = 0
endif endif
# Use make M=dir to specify direcotry of external module to build
# Old syntax make ... SUBDIRS=$PWD is still supported
# Setting the environment variable KBUILD_EXTMOD take precedence
ifdef SUBDIRS
KBUILD_EXTMOD ?= $(SUBDIRS)
endif
ifdef M
ifeq ("$(origin M)", "command line")
KBUILD_EXTMOD := $(M)
endif
endif
# kbuild supports saving output files in a separate directory. # kbuild supports saving output files in a separate directory.
# To locate output files in a separate directory two syntax'es are supported. # To locate output files in a separate directory two syntax'es are supported.
# In both cases the working directory must be the root of the kernel src. # In both cases the working directory must be the root of the kernel src.
...@@ -81,8 +94,8 @@ ifdef O ...@@ -81,8 +94,8 @@ ifdef O
endif endif
# That's our default target when none is given on the command line # That's our default target when none is given on the command line
.PHONY: all .PHONY: _all
all: _all:
ifneq ($(KBUILD_OUTPUT),) ifneq ($(KBUILD_OUTPUT),)
# Invoke a second make in the output directory, passing relevant variables # Invoke a second make in the output directory, passing relevant variables
...@@ -94,10 +107,11 @@ $(if $(wildcard $(KBUILD_OUTPUT)),, \ ...@@ -94,10 +107,11 @@ $(if $(wildcard $(KBUILD_OUTPUT)),, \
.PHONY: $(MAKECMDGOALS) .PHONY: $(MAKECMDGOALS)
$(filter-out all,$(MAKECMDGOALS)) all: $(filter-out _all,$(MAKECMDGOALS)) _all:
$(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \ $(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
KBUILD_SRC=$(CURDIR) KBUILD_VERBOSE=$(KBUILD_VERBOSE) \ KBUILD_SRC=$(CURDIR) KBUILD_VERBOSE=$(KBUILD_VERBOSE) \
KBUILD_CHECK=$(KBUILD_CHECK) -f $(CURDIR)/Makefile $@ KBUILD_CHECK=$(KBUILD_CHECK) KBUILD_EXTMOD=$(KBUILD_EXTMOD) \
-f $(CURDIR)/Makefile $@
# Leave processing to above invocation of make # Leave processing to above invocation of make
skip-makefile := 1 skip-makefile := 1
...@@ -107,6 +121,15 @@ endif # ifeq ($(KBUILD_SRC),) ...@@ -107,6 +121,15 @@ endif # ifeq ($(KBUILD_SRC),)
# We process the rest of the Makefile if this is the final invocation of make # We process the rest of the Makefile if this is the final invocation of make
ifeq ($(skip-makefile),) ifeq ($(skip-makefile),)
# If building an external module we do not care about the all: rule
# but instead _all depend on modules
.PHONY: all
ifeq ($(KBUILD_EXTMOD),)
_all: all
else
_all: modules
endif
# Make sure we're not wasting cpu-cycles doing locale handling, yet do make # Make sure we're not wasting cpu-cycles doing locale handling, yet do make
# sure error messages appear in the user-desired language # sure error messages appear in the user-desired language
ifdef LC_ALL ifdef LC_ALL
...@@ -194,7 +217,7 @@ endif ...@@ -194,7 +217,7 @@ endif
# in addition to whatever we do anyway. # in addition to whatever we do anyway.
# Just "make" or "make all" shall build modules as well # Just "make" or "make all" shall build modules as well
ifneq ($(filter all modules,$(MAKECMDGOALS)),) ifneq ($(filter all _all modules,$(MAKECMDGOALS)),)
KBUILD_MODULES := 1 KBUILD_MODULES := 1
endif endif
...@@ -203,7 +226,7 @@ ifeq ($(MAKECMDGOALS),) ...@@ -203,7 +226,7 @@ ifeq ($(MAKECMDGOALS),)
endif endif
export KBUILD_MODULES KBUILD_BUILTIN KBUILD_VERBOSE export KBUILD_MODULES KBUILD_BUILTIN KBUILD_VERBOSE
export KBUILD_CHECKSRC KBUILD_SRC export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD
# Beautify output # Beautify output
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
...@@ -299,7 +322,10 @@ export CPPFLAGS NOSTDINC_FLAGS OBJCOPYFLAGS LDFLAGS ...@@ -299,7 +322,10 @@ 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 # When compiling out-of-tree modules, put MODVERDIR in the module
# tree rather than in the kernel tree. The kernel tree might
# even be read-only.
export MODVERDIR := $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/).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
...@@ -340,11 +366,13 @@ ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),) ...@@ -340,11 +366,13 @@ ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
endif endif
endif endif
ifneq ($(filter config %config,$(MAKECMDGOALS)),) ifeq ($(KBUILD_EXTMOD),)
ifneq ($(filter config %config,$(MAKECMDGOALS)),)
config-targets := 1 config-targets := 1
ifneq ($(filter-out config %config,$(MAKECMDGOALS)),) ifneq ($(filter-out config %config,$(MAKECMDGOALS)),)
mixed-targets := 1 mixed-targets := 1
endif endif
endif
endif endif
ifeq ($(mixed-targets),1) ifeq ($(mixed-targets),1)
...@@ -371,6 +399,7 @@ else ...@@ -371,6 +399,7 @@ else
# Build targets only - this includes vmlinux, arch specific targets, clean # Build targets only - this includes vmlinux, arch specific targets, clean
# targets and others. In general all targets except *config targets. # targets and others. In general all targets except *config targets.
ifeq ($(KBUILD_EXTMOD),)
# Additional helpers built in scripts/ # Additional helpers built in scripts/
# Carefully list dependencies so we do not try to build scripts twice # Carefully list dependencies so we do not try to build scripts twice
# in parrallel # in parrallel
...@@ -393,7 +422,7 @@ drivers-y := drivers/ sound/ ...@@ -393,7 +422,7 @@ drivers-y := drivers/ sound/
net-y := net/ net-y := net/
libs-y := lib/ libs-y := lib/
core-y := usr/ core-y := usr/
SUBDIRS := endif # KBUILD_EXTMOD
ifeq ($(dot-config),1) ifeq ($(dot-config),1)
# In this section, we need .config # In this section, we need .config
...@@ -420,33 +449,6 @@ endif ...@@ -420,33 +449,6 @@ endif
include $(srctree)/arch/$(ARCH)/Makefile include $(srctree)/arch/$(ARCH)/Makefile
# Let architecture Makefiles change CPPFLAGS if needed
CFLAGS := $(CPPFLAGS) $(CFLAGS)
AFLAGS := $(CPPFLAGS) $(AFLAGS)
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/
SUBDIRS += $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
$(core-y) $(core-m) $(drivers-y) $(drivers-m) \
$(net-y) $(net-m) $(libs-y) $(libs-m)))
ALL_SUBDIRS := $(sort $(SUBDIRS) $(patsubst %/,%,$(filter %/, \
$(init-n) $(init-) \
$(core-n) $(core-) $(drivers-n) $(drivers-) \
$(net-n) $(net-) $(libs-n) $(libs-))))
init-y := $(patsubst %/, %/built-in.o, $(init-y))
core-y := $(patsubst %/, %/built-in.o, $(core-y))
drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y))
net-y := $(patsubst %/, %/built-in.o, $(net-y))
libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))
libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y))
libs-y := $(libs-y1) $(libs-y2)
# Here goes the main Makefile
# ---------------------------------------------------------------------------
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
CFLAGS += -Os CFLAGS += -Os
else else
...@@ -480,6 +482,27 @@ CFLAGS += $(call check_gcc,-Wdeclaration-after-statement,) ...@@ -480,6 +482,27 @@ CFLAGS += $(call check_gcc,-Wdeclaration-after-statement,)
MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE) MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
export MODLIB export MODLIB
ifeq ($(KBUILD_EXTMOD),)
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/
vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
$(core-y) $(core-m) $(drivers-y) $(drivers-m) \
$(net-y) $(net-m) $(libs-y) $(libs-m)))
vmlinux-alldirs := $(sort $(vmlinux-dirs) $(patsubst %/,%,$(filter %/, \
$(init-n) $(init-) \
$(core-n) $(core-) $(drivers-n) $(drivers-) \
$(net-n) $(net-) $(libs-n) $(libs-))))
init-y := $(patsubst %/, %/built-in.o, $(init-y))
core-y := $(patsubst %/, %/built-in.o, $(core-y))
drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y))
net-y := $(patsubst %/, %/built-in.o, $(net-y))
libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))
libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y))
libs-y := $(libs-y1) $(libs-y2)
# Build vmlinux # Build vmlinux
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
...@@ -568,12 +591,12 @@ vmlinux: $(vmlinux-objs) $(kallsyms.o) arch/$(ARCH)/kernel/vmlinux.lds.s FORCE ...@@ -568,12 +591,12 @@ vmlinux: $(vmlinux-objs) $(kallsyms.o) arch/$(ARCH)/kernel/vmlinux.lds.s FORCE
# The actual objects are generated when descending, # The actual objects are generated when descending,
# make sure no implicit rule kicks in # make sure no implicit rule kicks in
$(sort $(vmlinux-objs)) arch/$(ARCH)/kernel/vmlinux.lds.s: $(SUBDIRS) ; $(sort $(vmlinux-objs)) arch/$(ARCH)/kernel/vmlinux.lds.s: $(vmlinux-dirs) ;
# Handle descending into subdirectories listed in $(SUBDIRS) # Handle descending into subdirectories listed in $(vmlinux-dirs)
.PHONY: $(SUBDIRS) .PHONY: $(vmlinux-dirs)
$(SUBDIRS): prepare-all scripts $(vmlinux-dirs): prepare-all scripts
$(Q)$(MAKE) $(build)=$@ $(Q)$(MAKE) $(build)=$@
# Things we need to do before we recursively start building the kernel # Things we need to do before we recursively start building the kernel
...@@ -601,14 +624,7 @@ ifneq ($(KBUILD_SRC),) ...@@ -601,14 +624,7 @@ ifneq ($(KBUILD_SRC),)
endif endif
prepare0: prepare1 include/linux/version.h include/asm include/config/MARKER prepare0: prepare1 include/linux/version.h include/asm include/config/MARKER
ifdef KBUILD_MODULES
ifeq ($(origin SUBDIRS),file)
$(Q)rm -rf $(MODVERDIR) $(Q)rm -rf $(MODVERDIR)
else
@echo '*** Warning: Overriding SUBDIRS on the command line can cause'
@echo '*** inconsistencies'
endif
endif
$(if $(CONFIG_MODULES),$(Q)mkdir -p $(MODVERDIR)) $(if $(CONFIG_MODULES),$(Q)mkdir -p $(MODVERDIR))
# All the preparing.. # All the preparing..
...@@ -693,7 +709,7 @@ all: modules ...@@ -693,7 +709,7 @@ all: modules
# Build modules # Build modules
.PHONY: modules .PHONY: modules
modules: $(SUBDIRS) $(if $(KBUILD_BUILTIN),vmlinux) modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux)
@echo ' Building modules, stage 2.'; @echo ' Building modules, stage 2.';
$(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
...@@ -786,14 +802,13 @@ CLEAN_FILES += vmlinux System.map kernel.spec \ ...@@ -786,14 +802,13 @@ CLEAN_FILES += vmlinux System.map kernel.spec \
MRPROPER_DIRS += include/config include2 MRPROPER_DIRS += include/config include2
MRPROPER_FILES += .config .config.old include/asm .version \ MRPROPER_FILES += .config .config.old include/asm .version \
include/linux/autoconf.h include/linux/version.h \ include/linux/autoconf.h include/linux/version.h \
include/linux/modversions.h \ Module.symvers tags TAGS cscope*
tags TAGS cscope*
# clean - Delete most, but leave enough to build external modules # clean - Delete most, but leave enough to build external modules
# #
clean: rm-dirs := $(CLEAN_DIRS) clean: rm-dirs := $(CLEAN_DIRS)
clean: rm-files := $(CLEAN_FILES) clean: rm-files := $(CLEAN_FILES)
clean-dirs := $(addprefix _clean_,$(ALL_SUBDIRS)) clean-dirs := $(addprefix _clean_,$(vmlinux-alldirs))
.PHONY: $(clean-dirs) clean archclean .PHONY: $(clean-dirs) clean archclean
$(clean-dirs): $(clean-dirs):
...@@ -833,52 +848,6 @@ distclean: mrproper ...@@ -833,52 +848,6 @@ distclean: mrproper
-o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \ -o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \
-type f -print | xargs rm -f -type f -print | xargs rm -f
# Generate tags for editors
# ---------------------------------------------------------------------------
define all-sources
( find . $(RCS_FIND_IGNORE) \
\( -name include -o -name arch \) -prune -o \
-name '*.[chS]' -print; \
find arch/$(ARCH) $(RCS_FIND_IGNORE) \
-name '*.[chS]' -print; \
find include $(RCS_FIND_IGNORE) \
\( -name config -o -name 'asm-*' \) -prune \
-o -name '*.[chS]' -print; \
find include/asm-$(ARCH) $(RCS_FIND_IGNORE) \
-name '*.[chS]' -print; \
find include/asm-generic $(RCS_FIND_IGNORE) \
-name '*.[chS]' -print )
endef
quiet_cmd_cscope-file = FILELST cscope.files
cmd_cscope-file = $(all-sources) > cscope.files
quiet_cmd_cscope = MAKE cscope.out
cmd_cscope = cscope -k -b -q
cscope: FORCE
$(call cmd,cscope-file)
$(call cmd,cscope)
quiet_cmd_TAGS = MAKE $@
cmd_TAGS = $(all-sources) | etags -
# Exuberant ctags works better with -I
quiet_cmd_tags = MAKE $@
define cmd_tags
rm -f $@; \
CTAGSF=`ctags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_NOVERS"`; \
$(all-sources) | xargs ctags $$CTAGSF -a
endef
TAGS: FORCE
$(call cmd,TAGS)
tags: FORCE
$(call cmd,tags)
# RPM target # RPM target
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
...@@ -961,6 +930,110 @@ help: ...@@ -961,6 +930,110 @@ help:
%docs: scripts_basic FORCE %docs: scripts_basic FORCE
$(Q)$(MAKE) $(build)=Documentation/DocBook $@ $(Q)$(MAKE) $(build)=Documentation/DocBook $@
else # KBUILD_EXTMOD
###
# External module support.
# When building external modules the kernel used as basis is considered
# read-only, and no consistency checks are made and the make
# system is not used on the basis kernel. If updates are required
# in the basis kernel ordinary make commands (without M=...) must
# be used.
#
# The following are the only valid targets when building external
# modules.
# make M=dir clean Delete all automatically generated files
# make M=dir modules Make all modules in specified dir
# make M=dir Same as 'make M=dir modules'
# make M=dir modules_install
# Install the modules build in the module directory
# Assumes install directory is already created
# We are always building modules
KBUILD_MODULES := 1
.PHONY: $(KBUILD_EXTMOD)
$(KBUILD_EXTMOD): FORCE
$(Q)$(MAKE) $(build)=$@
.PHONY: modules
modules: $(KBUILD_EXTMOD)
@echo ' Building modules, stage 2.';
$(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
.PHONY: modules_install
modules_install:
$(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modinst
clean-dirs := _clean_$(KBUILD_EXTMOD)
.PHONY: $(clean-dirs) clean
$(clean-dirs):
$(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
clean: $(clean-dirs)
@find $(KBUILD_EXTMOD) $(RCS_FIND_IGNORE) \
\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \
-type f -print | xargs rm -f
help:
@echo ' Building external modules.'
@echo ' Syntax: make -C path/to/kernel/src M=$$PWD target'
@echo ''
@echo ' modules - default target, build the module(s)'
@echo ' modules_install - install the module'
@echo ' clean - remove generated files in module directory only'
@echo ''
endif # KBUILD_EXTMOD
# Generate tags for editors
# ---------------------------------------------------------------------------
define all-sources
( find . $(RCS_FIND_IGNORE) \
\( -name include -o -name arch \) -prune -o \
-name '*.[chS]' -print; \
find arch/$(ARCH) $(RCS_FIND_IGNORE) \
-name '*.[chS]' -print; \
find include $(RCS_FIND_IGNORE) \
\( -name config -o -name 'asm-*' \) -prune \
-o -name '*.[chS]' -print; \
find include/asm-$(ARCH) $(RCS_FIND_IGNORE) \
-name '*.[chS]' -print; \
find include/asm-generic $(RCS_FIND_IGNORE) \
-name '*.[chS]' -print )
endef
quiet_cmd_cscope-file = FILELST cscope.files
cmd_cscope-file = $(all-sources) > cscope.files
quiet_cmd_cscope = MAKE cscope.out
cmd_cscope = cscope -k -b -q
cscope: FORCE
$(call cmd,cscope-file)
$(call cmd,cscope)
quiet_cmd_TAGS = MAKE $@
cmd_TAGS = $(all-sources) | etags -
# Exuberant ctags works better with -I
quiet_cmd_tags = MAKE $@
define cmd_tags
rm -f $@; \
CTAGSF=`ctags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_NOVERS"`; \
$(all-sources) | xargs ctags $$CTAGSF -a
endef
TAGS: FORCE
$(call cmd,TAGS)
tags: FORCE
$(call cmd,tags)
# Scripts to check various things for consistency # Scripts to check various things for consistency
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
......
...@@ -13,12 +13,6 @@ include scripts/Makefile.lib ...@@ -13,12 +13,6 @@ include scripts/Makefile.lib
__modules := $(shell head -q -n1 /dev/null $(wildcard $(MODVERDIR)/*.mod)) __modules := $(shell head -q -n1 /dev/null $(wildcard $(MODVERDIR)/*.mod))
modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o))) modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o)))
ifneq ($(filter-out $(modules),$(__modules)),)
$(warning Trouble: $(filter-out $(modules),$(__modules)))
$(warning *** Uh-oh, you have stale module entries. You messed with SUBDIRS,)
$(warning do not complain if something goes wrong.)
endif
__modversions: $(modules) __modversions: $(modules)
@: @:
...@@ -55,9 +49,11 @@ $(modules:.ko=.mod.c): __modpost ; ...@@ -55,9 +49,11 @@ $(modules:.ko=.mod.c): __modpost ;
# Extract all checksums for all exported symbols # Extract all checksums for all exported symbols
quiet_cmd_modpost = MODPOST quiet_cmd_modpost = MODPOST
cmd_modpost = scripts/modpost $(filter-out FORCE,$^) cmd_modpost = scripts/modpost \
$(if $(filter vmlinux,$^),-o,-i) $(objtree)/Module.symvers \
$(filter-out FORCE,$^)
__modpost: $(wildcard vmlinux) $(modules:.ko=.o) FORCE __modpost: $(if $(KBUILD_EXTMOD),,$(wildcard vmlinux)) $(modules:.ko=.o) FORCE
$(call if_changed,modpost) $(call if_changed,modpost)
targets += __modpost targets += __modpost
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
/* Are we using CONFIG_MODVERSIONS? */ /* Are we using CONFIG_MODVERSIONS? */
int modversions = 0; int modversions = 0;
/* Do we have vmlinux? */ /* Warn about undefined symbols? (do so if we have vmlinux) */
int have_vmlinux = 0; int have_vmlinux = 0;
void void
...@@ -58,6 +58,17 @@ void *do_nofail(void *ptr, const char *file, int line, const char *expr) ...@@ -58,6 +58,17 @@ void *do_nofail(void *ptr, const char *file, int line, const char *expr)
static struct module *modules; static struct module *modules;
struct module *
find_module(char *modname)
{
struct module *mod;
for (mod = modules; mod; mod = mod->next)
if (strcmp(mod->name, modname) == 0)
break;
return mod;
}
struct module * struct module *
new_module(char *modname) new_module(char *modname)
{ {
...@@ -181,7 +192,7 @@ grab_file(const char *filename, unsigned long *size) ...@@ -181,7 +192,7 @@ grab_file(const char *filename, unsigned long *size)
int fd; int fd;
fd = open(filename, O_RDONLY); fd = open(filename, O_RDONLY);
if (fstat(fd, &st) != 0) if (fd < 0 || fstat(fd, &st) != 0)
return NULL; return NULL;
*size = st.st_size; *size = st.st_size;
...@@ -402,6 +413,8 @@ read_symbols(char *modname) ...@@ -402,6 +413,8 @@ read_symbols(char *modname)
/* May not have this if !CONFIG_MODULE_UNLOAD: fake it. /* May not have this if !CONFIG_MODULE_UNLOAD: fake it.
If it appears, we'll get the real CRC. */ If it appears, we'll get the real CRC. */
add_exported_symbol("cleanup_module", mod, &fake_crc); add_exported_symbol("cleanup_module", mod, &fake_crc);
add_exported_symbol("struct_module", mod, &fake_crc);
mod->skip = 1;
} }
for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
...@@ -604,19 +617,106 @@ write_if_changed(struct buffer *b, const char *fname) ...@@ -604,19 +617,106 @@ write_if_changed(struct buffer *b, const char *fname)
fclose(file); fclose(file);
} }
void
read_dump(const char *fname)
{
unsigned long size, pos = 0;
void *file = grab_file(fname, &size);
char *line;
if (!file) {
perror(fname);
abort();
}
while ((line = get_next_line(&pos, file, size))) {
char *symname, *modname, *d;
unsigned int crc;
struct module *mod;
if (!(symname = strchr(line, '\t')))
goto fail;
*symname++ = '\0';
if (!(modname = strchr(symname, '\t')))
goto fail;
*modname++ = '\0';
if (strchr(modname, '\t'))
goto fail;
crc = strtoul(line, &d, 16);
if (*symname == '\0' || *modname == '\0' || *d != '\0')
goto fail;
if (!(mod = find_module(modname))) {
if (is_vmlinux(modname)) {
modversions = 1;
have_vmlinux = 1;
}
mod = new_module(NOFAIL(strdup(modname)));
mod->skip = 1;
}
add_exported_symbol(symname, mod, &crc);
}
return;
fail:
fatal("parse error in symbol dump file\n");
}
void
write_dump(const char *fname)
{
struct buffer buf = { };
struct symbol *symbol;
int n;
for (n = 0; n < SYMBOL_HASH_SIZE ; n++) {
symbol = symbolhash[n];
while (symbol) {
symbol = symbol->next;
}
}
for (n = 0; n < SYMBOL_HASH_SIZE ; n++) {
symbol = symbolhash[n];
while (symbol) {
buf_printf(&buf, "0x%08x\t%s\t%s\n", symbol->crc,
symbol->name, symbol->module->name);
symbol = symbol->next;
}
}
write_if_changed(&buf, fname);
}
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
struct module *mod; struct module *mod;
struct buffer buf = { }; struct buffer buf = { };
char fname[SZ]; char fname[SZ];
char *dump_read = NULL, *dump_write = NULL;
int opt;
while ((opt = getopt(argc, argv, "i:o:")) != -1) {
switch(opt) {
case 'i':
dump_read = optarg;
break;
case 'o':
dump_write = optarg;
break;
default:
exit(1);
}
}
for (; argv[1]; argv++) { if (dump_read)
read_symbols(argv[1]); read_dump(dump_read);
while (optind < argc) {
read_symbols(argv[optind++]);
} }
for (mod = modules; mod; mod = mod->next) { for (mod = modules; mod; mod = mod->next) {
if (is_vmlinux(mod->name)) if (mod->skip)
continue; continue;
buf.pos = 0; buf.pos = 0;
...@@ -629,6 +729,10 @@ main(int argc, char **argv) ...@@ -629,6 +729,10 @@ main(int argc, char **argv)
sprintf(fname, "%s.mod.c", mod->name); sprintf(fname, "%s.mod.c", mod->name);
write_if_changed(&buf, fname); write_if_changed(&buf, fname);
} }
if (dump_write)
write_dump(dump_write);
return 0; return 0;
} }
...@@ -73,6 +73,7 @@ struct module { ...@@ -73,6 +73,7 @@ struct module {
const char *name; const char *name;
struct symbol *unres; struct symbol *unres;
int seen; int seen;
int skip;
struct buffer dev_table_buf; struct buffer dev_table_buf;
}; };
......
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