Merge master.kernel.org:/pub/scm/linux/kernel/git/sam/kbuild
authorLinus Torvalds <torvalds@g5.osdl.org>
Sat, 25 Mar 2006 16:48:48 +0000 (08:48 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Sat, 25 Mar 2006 16:48:48 +0000 (08:48 -0800)
* master.kernel.org:/pub/scm/linux/kernel/git/sam/kbuild: (46 commits)
  kbuild: remove obsoleted scripts/reference_* files
  kbuild: fix make help & make *pkg
  kconfig: fix time ordering of writes to .kconfig.d and include/linux/autoconf.h
  Kconfig: remove the CONFIG_CC_ALIGN_* options
  kbuild: add -fverbose-asm to i386 Makefile
  kbuild: clean-up genksyms
  kbuild: Lindent genksyms.c
  kbuild: fix genksyms build error
  kbuild: in makefile.txt note that Makefile is preferred name for kbuild files
  kbuild: replace PHONY with FORCE
  kbuild: Fix bug in crc symbol generating of kernel and modules
  kbuild: change kbuild to not rely on incorrect GNU make behavior
  kbuild: when warning symbols exported twice now tell user this is the problem
  kbuild: fix make dir/file.xx when asm symlink is missing
  kbuild: in the section mismatch check try harder to find symbols
  kbuild: fix section mismatch check for unwind on IA64
  kbuild: kill false positives from section mismatch warnings for powerpc
  kbuild: kill trailing whitespace in modpost & friends
  kbuild: small update of allnoconfig description
  kbuild: make namespace.pl CROSS_COMPILE happy
  ...

Trivial conflict in arch/ppc/boot/Makefile manually fixed up

1  2 
Documentation/DocBook/Makefile
Makefile
arch/arm/Makefile
arch/i386/kernel/vmlinux.lds.S
arch/m32r/Makefile
arch/powerpc/Makefile
init/Kconfig
scripts/Makefile.modpost
scripts/mod/file2alias.c
scripts/mod/modpost.c

@@@ -9,7 -9,7 +9,7 @@@
  DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
            kernel-hacking.xml kernel-locking.xml deviceiobook.xml \
            procfs-guide.xml writing_usb_driver.xml \
 -          sis900.xml kernel-api.xml journal-api.xml lsm.xml usb.xml \
 +          kernel-api.xml journal-api.xml lsm.xml usb.xml \
            gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml
  
  ###
@@@ -28,7 -28,7 +28,7 @@@ PS_METHOD     = $(prefer-db2x
  
  ###
  # The targets that may be used.
.PHONY:       xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs
PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs
  
  BOOKS := $(addprefix $(obj)/,$(DOCBOOKS))
  xmldocs: $(BOOKS)
@@@ -211,3 -211,9 +211,9 @@@ clean-dirs := $(patsubst %.xml,%,$(DOCB
  
  #man put files in man subdir - traverse down
  subdir- := man/
+ # Declare the contents of the .PHONY variable as phony.  We keep that
+ # information in a variable se we can use it in if_changed and friends.
+ .PHONY: $(PHONY)
diff --combined Makefile
+++ b/Makefile
@@@ -1,7 -1,7 +1,7 @@@
  VERSION = 2
  PATCHLEVEL = 6
  SUBLEVEL = 16
 -EXTRAVERSION =-rc4
 +EXTRAVERSION =
  NAME=Sliding Snow Leopard
  
  # *DOCUMENTATION*
@@@ -95,7 -95,7 +95,7 @@@ ifdef 
  endif
  
  # That's our default target when none is given on the command line
.PHONY: _all
PHONY := _all
  _all:
  
  ifneq ($(KBUILD_OUTPUT),)
@@@ -106,7 -106,7 +106,7 @@@ KBUILD_OUTPUT := $(shell cd $(KBUILD_OU
  $(if $(KBUILD_OUTPUT),, \
       $(error output directory "$(saved-output)" does not exist))
  
.PHONY: $(MAKECMDGOALS)
PHONY += $(MAKECMDGOALS)
  
  $(filter-out _all,$(MAKECMDGOALS)) _all:
        $(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
@@@ -123,7 -123,7 +123,7 @@@ ifeq ($(skip-makefile),
  
  # If building an external module we do not care about the all: rule
  # but instead _all depend on modules
.PHONY: all
PHONY += all
  ifeq ($(KBUILD_EXTMOD),)
  _all: all
  else
@@@ -137,7 -137,7 +137,7 @@@ objtree            := $(CURDIR
  src           := $(srctree)
  obj           := $(objtree)
  
- VPATH         := $(srctree)
+ VPATH         := $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD))
  
  export srctree objtree VPATH TOPDIR
  
  SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
                                  -e s/arm.*/arm/ -e s/sa110/arm/ \
                                  -e s/s390x/s390/ -e s/parisc64/parisc/ \
-                                 -e s/ppc.*/powerpc/ )
+                                 -e s/ppc.*/powerpc/ -e s/mips.*/mips/ )
  
  # Cross compiling and selecting different set of gcc/bin-utils
  # ---------------------------------------------------------------------------
@@@ -258,38 -258,6 +258,6 @@@ endi
  
  export quiet Q KBUILD_VERBOSE
  
- ######
- # cc support functions to be used (only) in arch/$(ARCH)/Makefile
- # See documentation in Documentation/kbuild/makefiles.txt
- # as-option
- # Usage: cflags-y += $(call as-option, -Wa$(comma)-isa=foo,)
- as-option = $(shell if $(CC) $(CFLAGS) $(1) -Wa,-Z -c -o /dev/null \
-            -xassembler /dev/null > /dev/null 2>&1; then echo "$(1)"; \
-            else echo "$(2)"; fi ;)
- # cc-option
- # Usage: cflags-y += $(call cc-option, -march=winchip-c6, -march=i586)
- cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
-              > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
- # cc-option-yn
- # Usage: flag := $(call cc-option-yn, -march=winchip-c6)
- cc-option-yn = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
-                 > /dev/null 2>&1; then echo "y"; else echo "n"; fi;)
- # cc-option-align
- # Prefix align with either -falign or -malign
- cc-option-align = $(subst -functions=0,,\
-       $(call cc-option,-falign-functions=0,-malign-functions=0))
- # cc-version
- # Usage gcc-ver := $(call cc-version $(CC))
- cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh \
-               $(if $(1), $(1), $(CC)))
  
  # Look for make include files relative to root of kernel src
  MAKEFLAGS += --include-dir=$(srctree)
@@@ -369,14 -337,14 +337,14 @@@ export RCS_TAR_IGNORE := --exclude SCC
  # Rules shared between *config targets and build targets
  
  # Basic helpers built in scripts/
.PHONY: scripts_basic
PHONY += scripts_basic
  scripts_basic:
        $(Q)$(MAKE) $(build)=scripts/basic
  
  # To avoid any implicit rule to kick in, define an empty command.
  scripts/basic/%: scripts_basic ;
  
.PHONY: outputmakefile
PHONY += outputmakefile
  # outputmakefile generate a Makefile to be placed in output directory, if
  # using a seperate output directory. This allows convinient use
  # of make in output directory
@@@ -452,7 -420,7 +420,7 @@@ ifeq ($(KBUILD_EXTMOD),
  # Additional helpers built in scripts/
  # Carefully list dependencies so we do not try to build scripts twice
  # in parrallel
.PHONY: scripts
PHONY += scripts
  scripts: scripts_basic include/config/MARKER
        $(Q)$(MAKE) $(build)=$(@)
  
@@@ -504,23 -472,12 +472,16 @@@ els
  CFLAGS                += -O2
  endif
  
- #Add align options if CONFIG_CC_* is not equal to 0
- add-align = $(if $(filter-out 0,$($(1))),$(cc-option-align)$(2)=$($(1)))
- CFLAGS                += $(call add-align,CONFIG_CC_ALIGN_FUNCTIONS,-functions)
- CFLAGS                += $(call add-align,CONFIG_CC_ALIGN_LABELS,-labels)
- CFLAGS                += $(call add-align,CONFIG_CC_ALIGN_LOOPS,-loops)
- CFLAGS                += $(call add-align,CONFIG_CC_ALIGN_JUMPS,-jumps)
  ifdef CONFIG_FRAME_POINTER
  CFLAGS                += -fno-omit-frame-pointer $(call cc-option,-fno-optimize-sibling-calls,)
  else
  CFLAGS                += -fomit-frame-pointer
  endif
  
 +ifdef CONFIG_UNWIND_INFO
 +CFLAGS                += -fasynchronous-unwind-tables
 +endif
 +
  ifdef CONFIG_DEBUG_INFO
  CFLAGS                += -g
  endif
@@@ -756,7 -713,7 +717,7 @@@ $(sort $(vmlinux-init) $(vmlinux-main)
  # make menuconfig etc.
  # Error messages still appears in the original language
  
.PHONY: $(vmlinux-dirs)
PHONY += $(vmlinux-dirs)
  $(vmlinux-dirs): prepare scripts
        $(Q)$(MAKE) $(build)=$@
  
@@@ -809,10 -766,10 +770,10 @@@ kernelrelease = $(KERNELVERSION)$(local
  # version.h and scripts_basic is processed / created.
  
  # Listed in dependency order
.PHONY: prepare archprepare prepare0 prepare1 prepare2 prepare3
PHONY += prepare archprepare prepare0 prepare1 prepare2 prepare3
  
  # prepare-all is deprecated, use prepare as valid replacement
.PHONY: prepare-all
PHONY += prepare-all
  
  # prepare3 is used to check if we are building in a separate output directory,
  # and if so do:
@@@ -853,27 -810,6 +814,6 @@@ prepare prepare-all: prepare
  
  export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
  
- # Single targets
- # ---------------------------------------------------------------------------
- %.s: %.c scripts FORCE
-       $(Q)$(MAKE) $(build)=$(@D) $@
- %.i: %.c scripts FORCE
-       $(Q)$(MAKE) $(build)=$(@D) $@
- %.o: %.c scripts FORCE
-       $(Q)$(MAKE) $(build)=$(@D) $@
- %.ko: scripts FORCE
-       $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) $(build)=$(@D) $(@:.ko=.o)
-       $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
- %/:      scripts prepare FORCE
-       $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) $(build)=$(@D)
- %.lst: %.c scripts FORCE
-       $(Q)$(MAKE) $(build)=$(@D) $@
- %.s: %.S scripts FORCE
-       $(Q)$(MAKE) $(build)=$(@D) $@
- %.o: %.S scripts FORCE
-       $(Q)$(MAKE) $(build)=$(@D) $@
  #     FIXME: The asm symlink changes when $(ARCH) changes. That's
  #     hard to detect, but I suppose "make mrproper" is a good idea
  #     before switching between archs anyway.
@@@ -914,7 -850,7 +854,7 @@@ include/linux/version.h: $(srctree)/Mak
  
  # ---------------------------------------------------------------------------
  
.PHONY: depend dep
PHONY += depend dep
  depend dep:
        @echo '*** Warning: make $@ is unnecessary now.'
  
@@@ -929,21 -865,21 +869,21 @@@ all: module
  
  #     Build modules
  
.PHONY: modules
PHONY += modules
  modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux)
        @echo '  Building modules, stage 2.';
        $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
  
  
  # Target to prepare building external modules
.PHONY: modules_prepare
PHONY += modules_prepare
  modules_prepare: prepare scripts
  
  # Target to install modules
.PHONY: modules_install
PHONY += modules_install
  modules_install: _modinst_ _modinst_post
  
.PHONY: _modinst_
PHONY += _modinst_
  _modinst_:
        @if [ -z "`$(DEPMOD) -V 2>/dev/null | grep module-init-tools`" ]; then \
                echo "Warning: you may need to install module-init-tools"; \
@@@ -970,7 -906,7 +910,7 @@@ depmod_opts        :
  else
  depmod_opts   := -b $(INSTALL_MOD_PATH) -r
  endif
.PHONY: _modinst_post
PHONY += _modinst_post
  _modinst_post: _modinst_
        if [ -r System.map -a -x $(DEPMOD) ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi
  
@@@ -1013,7 -949,7 +953,7 @@@ clean: rm-dirs  := $(CLEAN_DIRS
  clean: rm-files := $(CLEAN_FILES)
  clean-dirs      := $(addprefix _clean_,$(srctree) $(vmlinux-alldirs))
  
.PHONY: $(clean-dirs) clean archclean
PHONY += $(clean-dirs) clean archclean
  $(clean-dirs):
        $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
  
@@@ -1031,7 -967,7 +971,7 @@@ mrproper: rm-dirs  := $(wildcard $(MRPR
  mrproper: rm-files := $(wildcard $(MRPROPER_FILES))
  mrproper-dirs      := $(addprefix _mrproper_,Documentation/DocBook scripts)
  
.PHONY: $(mrproper-dirs) mrproper archmrproper
PHONY += $(mrproper-dirs) mrproper archmrproper
  $(mrproper-dirs):
        $(Q)$(MAKE) $(clean)=$(patsubst _mrproper_%,%,$@)
  
@@@ -1041,7 -977,7 +981,7 @@@ mrproper: clean archmrproper $(mrproper
  
  # distclean
  #
.PHONY: distclean
PHONY += distclean
  
  distclean: mrproper
        @find $(srctree) $(RCS_FIND_IGNORE) \
  # rpm target kept for backward compatibility
  package-dir   := $(srctree)/scripts/package
  
- .PHONY: %-pkg rpm
  %pkg: FORCE
-       $(Q)$(MAKE) -f $(package-dir)/Makefile $@
+       $(Q)$(MAKE) $(build)=$(package-dir) $@
  rpm: FORCE
-       $(Q)$(MAKE) -f $(package-dir)/Makefile $@
+       $(Q)$(MAKE) $(build)=$(package-dir) $@
  
  
  # Brief documentation of the typical targets used
@@@ -1094,13 -1028,11 +1032,11 @@@ help
        @echo  '  kernelversion   - Output the version stored in Makefile'
        @echo  ''
        @echo  'Static analysers'
-       @echo  '  buildcheck      - List dangling references to vmlinux discarded sections'
-       @echo  '                    and init sections from non-init sections'
        @echo  '  checkstack      - Generate a list of stack hogs'
        @echo  '  namespacecheck  - Name space analysis on compiled kernel'
        @echo  ''
        @echo  'Kernel packaging:'
-       @$(MAKE) -f $(package-dir)/Makefile help
+       @$(MAKE) $(build)=$(package-dir) help
        @echo  ''
        @echo  'Documentation targets:'
        @$(MAKE) -f $(srctree)/Documentation/DocBook/Makefile dochelp
@@@ -1149,11 -1081,12 +1085,12 @@@ else # KBUILD_EXTMO
  
  # We are always building modules
  KBUILD_MODULES := 1
.PHONY: crmodverdir
PHONY += crmodverdir
  crmodverdir:
+       $(Q)rm -rf $(MODVERDIR)
        $(Q)mkdir -p $(MODVERDIR)
  
.PHONY: $(objtree)/Module.symvers
PHONY += $(objtree)/Module.symvers
  $(objtree)/Module.symvers:
        @test -e $(objtree)/Module.symvers || ( \
        echo; \
        echo )
  
  module-dirs := $(addprefix _module_,$(KBUILD_EXTMOD))
.PHONY: $(module-dirs) modules
PHONY += $(module-dirs) modules
  $(module-dirs): crmodverdir $(objtree)/Module.symvers
        $(Q)$(MAKE) $(build)=$(patsubst _module_%,%,$@)
  
@@@ -1170,13 -1103,32 +1107,32 @@@ modules: $(module-dirs
        @echo '  Building modules, stage 2.';
        $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
  
- .PHONY: modules_install
- modules_install:
+ PHONY += modules_install
+ modules_install: _emodinst_ _emodinst_post
+ install-dir := $(if $(INSTALL_MOD_DIR),$(INSTALL_MOD_DIR),extra)
+ PHONY += _emodinst_
+ _emodinst_:
+       $(Q)rm -rf $(MODLIB)/$(install-dir)
+       $(Q)mkdir -p $(MODLIB)/$(install-dir)
        $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modinst
  
+ # Run depmod only is we have System.map and depmod is executable
+ quiet_cmd_depmod = DEPMOD  $(KERNELRELEASE)
+       cmd_depmod = if [ -r System.map -a -x $(DEPMOD) ]; then \
+                       $(DEPMOD) -ae -F System.map             \
+                       $(if $(strip $(INSTALL_MOD_PATH)),      \
+                     -b $(INSTALL_MOD_PATH) -r)              \
+                     $(KERNELRELEASE);                       \
+                    fi
+ PHONY += _emodinst_post
+ _emodinst_post: _emodinst_
+       $(call cmd,depmod)
  clean-dirs := $(addprefix _clean_,$(KBUILD_EXTMOD))
  
.PHONY: $(clean-dirs) clean
PHONY += $(clean-dirs) clean
  $(clean-dirs):
        $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
  
@@@ -1196,6 -1148,11 +1152,11 @@@ help
        @echo  '  modules_install - install the module'
        @echo  '  clean           - remove generated files in module directory only'
        @echo  ''
+ # Dummies...
+ PHONY += prepare scripts
+ prepare: ;
+ scripts: ;
  endif # KBUILD_EXTMOD
  
  # Generate tags for editors
@@@ -1296,17 -1253,13 +1257,13 @@@ versioncheck
                -name '*.[hcS]' -type f -print | sort \
                | xargs $(PERL) -w scripts/checkversion.pl
  
- buildcheck:
-       $(PERL) $(srctree)/scripts/reference_discarded.pl
-       $(PERL) $(srctree)/scripts/reference_init.pl
  namespacecheck:
        $(PERL) $(srctree)/scripts/namespace.pl
  
  endif #ifeq ($(config-targets),1)
  endif #ifeq ($(mixed-targets),1)
  
.PHONY: checkstack
PHONY += checkstack
  checkstack:
        $(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \
        $(PERL) $(src)/scripts/checkstack.pl $(ARCH)
@@@ -1317,6 -1270,44 +1274,44 @@@ kernelrelease
  kernelversion:
        @echo $(KERNELVERSION)
  
+ # Single targets
+ # ---------------------------------------------------------------------------
+ # The directory part is taken from first prerequisite, so this
+ # works even with external modules
+ %.s: %.c prepare scripts FORCE
+       $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
+ %.i: %.c prepare scripts FORCE
+       $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
+ %.o: %.c prepare scripts FORCE
+       $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
+ %.lst: %.c prepare scripts FORCE
+       $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
+ %.s: %.S prepare scripts FORCE
+       $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
+ %.o: %.S prepare scripts FORCE
+       $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
+ # For external modules we shall include any directory of the target,
+ # but usual case there is no directory part.
+ # make M=`pwd` module.o     => $(dir $@)=./
+ # make M=`pwd` foo/module.o => $(dir $@)=foo/
+ # make M=`pwd` /            => $(dir $@)=/
+  
+ ifeq ($(KBUILD_EXTMOD),)
+         target-dir = $(@D)
+ else
+         zap-slash=$(filter-out .,$(patsubst %/,%,$(dir $@)))
+         target-dir = $(KBUILD_EXTMOD)$(if $(zap-slash),/$(zap-slash))
+ endif
+ / %/:      scripts prepare FORCE
+       $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
+       $(build)=$(target-dir)
+ %.ko: scripts FORCE
+       $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1)   \
+       $(build)=$(target-dir) $(@:.ko=.o)
+       $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
  # FIXME Should go into a make.lib or something 
  # ===========================================================================
  
@@@ -1351,4 -1342,10 +1346,10 @@@ clean := -f $(if $(KBUILD_SRC),$(srctre
  
  endif # skip-makefile
  
+ PHONY += FORCE
  FORCE:
+ # Declare the contents of the .PHONY variable as phony.  We keep that
+ # information in a variable se we can use it in if_changed and friends.
+ .PHONY: $(PHONY)
diff --combined arch/arm/Makefile
@@@ -1,6 -1,9 +1,9 @@@
  #
  # arch/arm/Makefile
  #
+ # This file is included by the global makefile so that you can add your own
+ # architecture-specific flags and dependencies.
+ #
  # This file is subject to the terms and conditions of the GNU General Public
  # License.  See the file "COPYING" in the main directory of this archive
  # for more details.
@@@ -105,7 -108,6 +108,7 @@@ endi
   machine-$(CONFIG_ARCH_AAEC2000)   := aaec2000
   machine-$(CONFIG_ARCH_REALVIEW)   := realview
   machine-$(CONFIG_ARCH_AT91RM9200) := at91rm9200
 + machine-$(CONFIG_ARCH_EP93XX)     := ep93xx
  
  ifeq ($(CONFIG_ARCH_EBSA110),y)
  # This is what happens if you forget the IOCS16 line.
@@@ -177,7 -179,7 +180,7 @@@ endi
  
  archprepare: maketools
  
.PHONY: maketools FORCE
PHONY += maketools FORCE
  maketools: include/linux/version.h include/asm-arm/.arch FORCE
        $(Q)$(MAKE) $(build)=arch/arm/tools include/asm-arm/mach-types.h
  
@@@ -7,6 -7,7 +7,7 @@@
  #include <asm-generic/vmlinux.lds.h>
  #include <asm/thread_info.h>
  #include <asm/page.h>
+ #include <asm/cache.h>
  
  OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
  OUTPUT_ARCH(i386)
@@@ -68,26 -69,6 +69,26 @@@ SECTION
        *(.data.init_task)
    }
  
 +  /* might get freed after init */
 +  . = ALIGN(4096);
 +  __smp_alt_begin = .;
 +  __smp_alt_instructions = .;
 +  .smp_altinstructions : AT(ADDR(.smp_altinstructions) - LOAD_OFFSET) {
 +      *(.smp_altinstructions)
 +  }
 +  __smp_alt_instructions_end = .;
 +  . = ALIGN(4);
 +  __smp_locks = .;
 +  .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
 +      *(.smp_locks)
 +  }
 +  __smp_locks_end = .;
 +  .smp_altinstr_replacement : AT(ADDR(.smp_altinstr_replacement) - LOAD_OFFSET) {
 +      *(.smp_altinstr_replacement)
 +  }
 +  . = ALIGN(4096);
 +  __smp_alt_end = .;
 +
    /* will be freed after init */
    . = ALIGN(4096);            /* Init code and data */
    __init_begin = .;
    __initramfs_start = .;
    .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { *(.init.ramfs) }
    __initramfs_end = .;
-   . = ALIGN(32);
+   . = ALIGN(L1_CACHE_BYTES);
    __per_cpu_start = .;
    .data.percpu  : AT(ADDR(.data.percpu) - LOAD_OFFSET) { *(.data.percpu) }
    __per_cpu_end = .;
diff --combined arch/m32r/Makefile
@@@ -1,6 -1,9 +1,9 @@@
  #
  # m32r/Makefile
  #
+ # This file is included by the global makefile so that you can add your own
+ # architecture-specific flags and dependencies.
+ #
  
  LDFLAGS               :=
  OBJCOPYFLAGS  := -O binary -R .note -R .comment -S
@@@ -12,14 -15,14 +15,14 @@@ CFLAGS_MODULE += -mmodel=larg
  
  ifdef CONFIG_CHIP_VDEC2
  cflags-$(CONFIG_ISA_M32R2)    += -DNO_FPU -Wa,-bitinst
 -aflags-$(CONFIG_ISA_M32R2)    += -DNO_FPU -Wa,-bitinst
 +aflags-$(CONFIG_ISA_M32R2)    += -DNO_FPU -O2 -Wa,-bitinst -Wa,-no-parallel
  else
  cflags-$(CONFIG_ISA_M32R2)    += -DNO_FPU -m32r2
 -aflags-$(CONFIG_ISA_M32R2)    += -DNO_FPU -m32r2
 +aflags-$(CONFIG_ISA_M32R2)    += -DNO_FPU -m32r2 -O2
  endif
  
  cflags-$(CONFIG_ISA_M32R)     += -DNO_FPU
 -aflags-$(CONFIG_ISA_M32R)     += -DNO_FPU -Wa,-no-bitinst
 +aflags-$(CONFIG_ISA_M32R)     += -DNO_FPU -O2 -Wa,-no-bitinst
  
  CFLAGS += $(cflags-y)
  AFLAGS += $(aflags-y)
@@@ -39,7 -42,7 +42,7 @@@ drivers-$(CONFIG_OPROFILE)    += arch/m32r
  
  boot := arch/m32r/boot
  
.PHONY: zImage
PHONY += zImage
  
  all: zImage
  
diff --combined arch/powerpc/Makefile
@@@ -148,9 -148,9 +148,9 @@@ all: $(KBUILD_IMAGE
  
  CPPFLAGS_vmlinux.lds  := -Upowerpc
  
 -BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm uImage
 +BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm uImage vmlinux.bin
  
.PHONY: $(BOOT_TARGETS)
PHONY += $(BOOT_TARGETS)
  
  boot := arch/$(ARCH)/boot
  
diff --combined init/Kconfig
@@@ -214,17 -214,6 +214,17 @@@ config CPUSET
  
          Say N if unsure.
  
 +config RELAY
 +      bool "Kernel->user space relay support (formerly relayfs)"
 +      help
 +        This option enables support for relay interface support in
 +        certain file systems (such as debugfs).
 +        It is designed to provide an efficient mechanism for tools and
 +        facilities to relay large amounts of data from kernel space to
 +        user space.
 +
 +        If unsure, say N.
 +
  source "usr/Kconfig"
  
  config UID16
@@@ -365,43 -354,6 +365,6 @@@ config SHME
          option replaces shmem and tmpfs with the much simpler ramfs code,
          which may be appropriate on small systems without swap.
  
- config CC_ALIGN_FUNCTIONS
-       int "Function alignment" if EMBEDDED
-       default 0
-       help
-         Align the start of functions to the next power-of-two greater than n,
-         skipping up to n bytes.  For instance, 32 aligns functions
-         to the next 32-byte boundary, but 24 would align to the next
-         32-byte boundary only if this can be done by skipping 23 bytes or less.
-         Zero means use compiler's default.
- config CC_ALIGN_LABELS
-       int "Label alignment" if EMBEDDED
-       default 0
-       help
-         Align all branch targets to a power-of-two boundary, skipping
-         up to n bytes like ALIGN_FUNCTIONS.  This option can easily
-         make code slower, because it must insert dummy operations for
-         when the branch target is reached in the usual flow of the code.
-         Zero means use compiler's default.
- config CC_ALIGN_LOOPS
-       int "Loop alignment" if EMBEDDED
-       default 0
-       help
-         Align loops to a power-of-two boundary, skipping up to n bytes.
-         Zero means use compiler's default.
- config CC_ALIGN_JUMPS
-       int "Jump alignment" if EMBEDDED
-       default 0
-       help
-         Align branch targets to a power-of-two boundary, for branch
-         targets where the targets can only be reached by jumping,
-         skipping up to n bytes like ALIGN_FUNCTIONS.  In this case,
-         no dummy operations need be executed.
-         Zero means use compiler's default.
  config SLAB
        default y
        bool "Use full SLAB allocator" if EMBEDDED
@@@ -470,6 -422,15 +433,6 @@@ config MODULE_FORCE_UNLOA
          rmmod).  This is mainly for kernel developers and desperate users.
          If unsure, say N.
  
 -config OBSOLETE_MODPARM
 -      bool
 -      default y
 -      depends on MODULES
 -      help
 -        You need this option to use module parameters on modules which
 -        have not been converted to the new module parameter system yet.
 -        If unsure, say Y.
 -
  config MODVERSIONS
        bool "Module versioning support"
        depends on MODULES
diff --combined scripts/Makefile.modpost
@@@ -4,7 -4,7 +4,7 @@@
  #
  # Stage one of module building created the following:
  # a) The individual .o files used for the module
 -# b) A <module>.o file wich is the .o files above linked together
 +# b) A <module>.o file which is the .o files above linked together
  # c) A <module>.mod file in $(MODVERDIR)/, listing the name of the
  #    the preliminary <module>.o file, plus all .o files
  
  # Step 4 is solely used to allow module versioning in external modules,
  # where the CRC of each module is retrieved from the Module.symers file.
  
.PHONY: _modpost
PHONY := _modpost
  _modpost: __modpost
  
  include .config
  include scripts/Kbuild.include
  include scripts/Makefile.lib
  
- symverfile := $(objtree)/Module.symvers
+ kernelsymfile := $(objtree)/Module.symvers
+ modulesymfile := $(KBUILD_EXTMOD)/Modules.symvers
  
  # Step 1), find all modules listed in $(MODVERDIR)/
  __modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
@@@ -54,10 -55,12 +55,12 @@@ quiet_cmd_modpost = MODPOS
        cmd_modpost = scripts/mod/modpost            \
          $(if $(CONFIG_MODVERSIONS),-m)             \
        $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,)  \
-       $(if $(KBUILD_EXTMOD),-i,-o) $(symverfile) \
+       $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \
+       $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \
+       $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
        $(filter-out FORCE,$^)
  
.PHONY: __modpost
PHONY += __modpost
  __modpost: $(wildcard vmlinux) $(modules:.ko=.o) FORCE
        $(call cmd,modpost)
  
@@@ -94,7 -97,7 +97,7 @@@ targets += $(modules
  # Add FORCE to the prequisites of a target to force it to be always rebuilt.
  # ---------------------------------------------------------------------------
  
.PHONY: FORCE
PHONY += FORCE
  
  FORCE:
  
@@@ -109,3 -112,9 +112,9 @@@ cmd_files := $(wildcard $(foreach f,$(t
  ifneq ($(cmd_files),)
    include $(cmd_files)
  endif
+ # Declare the contents of the .PHONY variable as phony.  We keep that
+ # information in a variable se we can use it in if_changed and friends.
+ .PHONY: $(PHONY)
diff --combined scripts/mod/file2alias.c
@@@ -34,7 -34,7 +34,7 @@@ typedef uint16_t      __u16
  typedef unsigned char __u8;
  
  /* Big exception to the "don't include kernel headers into userspace, which
-  * even potentially has different endianness and word sizes, since 
+  * even potentially has different endianness and word sizes, since
   * we handle those differences explicitly below */
  #include "../../include/linux/mod_devicetable.h"
  #include "../../include/linux/input.h"
@@@ -153,8 -153,8 +153,8 @@@ static void do_usb_table(void *symval, 
        const unsigned long id_size = sizeof(struct usb_device_id);
  
        if (size % id_size || size < id_size) {
-               fprintf(stderr, "*** Warning: %s ids %lu bad size "
-                       "(each on %lu)\n", mod->name, size, id_size);
+               warn("%s ids %lu bad size "
+                    "(each on %lu)\n", mod->name, size, id_size);
        }
        /* Leave last one: it's the terminator. */
        size -= id_size;
@@@ -217,9 -217,8 +217,8 @@@ static int do_pci_entry(const char *fil
        if ((baseclass_mask != 0 && baseclass_mask != 0xFF)
            || (subclass_mask != 0 && subclass_mask != 0xFF)
            || (interface_mask != 0 && interface_mask != 0xFF)) {
-               fprintf(stderr,
-                       "*** Warning: Can't handle masks in %s:%04X\n",
-                       filename, id->class_mask);
+               warn("Can't handle masks in %s:%04X\n",
+                    filename, id->class_mask);
                return 0;
        }
  
        return 1;
  }
  
- /* looks like: "ccw:tNmNdtNdmN" */ 
+ /* looks like: "ccw:tNmNdtNdmN" */
  static int do_ccw_entry(const char *filename,
                        struct ccw_device_id *id, char *alias)
  {
            id->cu_model);
        ADD(alias, "dt", id->match_flags&CCW_DEVICE_ID_MATCH_DEVICE_TYPE,
            id->dev_type);
 -      ADD(alias, "dm", id->match_flags&CCW_DEVICE_ID_MATCH_DEVICE_TYPE,
 +      ADD(alias, "dm", id->match_flags&CCW_DEVICE_ID_MATCH_DEVICE_MODEL,
            id->dev_model);
        return 1;
  }
@@@ -445,8 -444,8 +444,8 @@@ static void do_table(void *symval, unsi
        int (*do_entry)(const char *, void *entry, char *alias) = function;
  
        if (size % id_size || size < id_size) {
-               fprintf(stderr, "*** Warning: %s ids %lu bad size "
-                       "(each on %lu)\n", mod->name, size, id_size);
+               warn("%s ids %lu bad size "
+                    "(each on %lu)\n", mod->name, size, id_size);
        }
        /* Leave last one: it's the terminator. */
        size -= id_size;
diff --combined scripts/mod/modpost.c
@@@ -2,7 -2,7 +2,7 @@@
   *
   * Copyright 2003       Kai Germaschewski
   * Copyright 2002-2004  Rusty Russell, IBM Corporation
-  *
+  * Copyright 2006       Sam Ravnborg
   * Based in part on module-init-tools/depmod.c,file2alias
   *
   * This software may be used and distributed according to the terms
@@@ -20,9 -20,10 +20,10 @@@ int modversions = 0
  int have_vmlinux = 0;
  /* Is CONFIG_MODULE_SRCVERSION_ALL set? */
  static int all_versions = 0;
+ /* If we are modposting external module set to 1 */
+ static int external_module = 0;
  
- void
- fatal(const char *fmt, ...)
+ void fatal(const char *fmt, ...)
  {
        va_list arglist;
  
@@@ -35,8 -36,7 +36,7 @@@
        exit(1);
  }
  
- void
- warn(const char *fmt, ...)
+ void warn(const char *fmt, ...)
  {
        va_list arglist;
  
        va_end(arglist);
  }
  
+ static int is_vmlinux(const char *modname)
+ {
+       const char *myname;
+       if ((myname = strrchr(modname, '/')))
+               myname++;
+       else
+               myname = modname;
+       return strcmp(myname, "vmlinux") == 0;
+ }
  void *do_nofail(void *ptr, const char *expr)
  {
        if (!ptr) {
@@@ -59,8 -71,7 +71,7 @@@
  
  static struct module *modules;
  
- struct module *
- find_module(char *modname)
+ static struct module *find_module(char *modname)
  {
        struct module *mod;
  
        return mod;
  }
  
- struct module *
- new_module(char *modname)
+ static struct module *new_module(char *modname)
  {
        struct module *mod;
        char *p, *s;
-       
        mod = NOFAIL(malloc(sizeof(*mod)));
        memset(mod, 0, sizeof(*mod));
        p = NOFAIL(strdup(modname));
@@@ -104,6 -114,10 +114,10 @@@ struct symbol 
        unsigned int crc;
        int crc_valid;
        unsigned int weak:1;
+       unsigned int vmlinux:1;    /* 1 if symbol is defined in vmlinux */
+       unsigned int kernel:1;     /* 1 if symbol is from kernel
+                                   *  (only for external modules) **/
+       unsigned int preloaded:1;  /* 1 if symbol from Module.symvers */
        char name[0];
  };
  
@@@ -122,11 -136,12 +136,12 @@@ static inline unsigned int tdb_hash(con
        return (1103515243 * value + 12345);
  }
  
- /* Allocate a new symbols for use in the hash of exported symbols or
-  * the list of unresolved symbols per module */
- struct symbol *
- alloc_symbol(const char *name, unsigned int weak, struct symbol *next)
+ /**
+  * Allocate a new symbols for use in the hash of exported symbols or
+  * the list of unresolved symbols per module
+  **/
+ static struct symbol *alloc_symbol(const char *name, unsigned int weak,
+                                  struct symbol *next)
  {
        struct symbol *s = NOFAIL(malloc(sizeof(*s) + strlen(name) + 1));
  
  }
  
  /* For the hash of exported symbols */
- void
- new_symbol(const char *name, struct module *module, unsigned int *crc)
+ static struct symbol *new_symbol(const char *name, struct module *module)
  {
        unsigned int hash;
        struct symbol *new;
        hash = tdb_hash(name) % SYMBOL_HASH_SIZE;
        new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]);
        new->module = module;
-       if (crc) {
-               new->crc = *crc;
-               new->crc_valid = 1;
-       }
+       return new;
  }
  
- struct symbol *
- find_symbol(const char *name)
+ static struct symbol *find_symbol(const char *name)
  {
        struct symbol *s;
  
        return NULL;
  }
  
- /* Add an exported symbol - it may have already been added without a
-  * CRC, in this case just update the CRC */
- void
- add_exported_symbol(const char *name, struct module *module, unsigned int *crc)
+ /**
+  * Add an exported symbol - it may have already been added without a
+  * CRC, in this case just update the CRC
+  **/
+ static struct symbol *sym_add_exported(const char *name, struct module *mod)
  {
        struct symbol *s = find_symbol(name);
  
        if (!s) {
-               new_symbol(name, module, crc);
-               return;
-       }
-       if (crc) {
-               s->crc = *crc;
-               s->crc_valid = 1;
+               s = new_symbol(name, mod);
+       } else {
+               if (!s->preloaded) {
+                       warn("%s: '%s' exported twice. Previous export "
+                            "was in %s%s\n", mod->name, name,
+                            s->module->name,
+                            is_vmlinux(s->module->name) ?"":".ko");
+               }
        }
+       s->preloaded = 0;
+       s->vmlinux   = is_vmlinux(mod->name);
+       s->kernel    = 0;
+       return s;
+ }
+ static void sym_update_crc(const char *name, struct module *mod,
+                          unsigned int crc)
+ {
+       struct symbol *s = find_symbol(name);
+       if (!s)
+               s = new_symbol(name, mod);
+       s->crc = crc;
+       s->crc_valid = 1;
  }
  
- void *
- grab_file(const char *filename, unsigned long *size)
+ void *grab_file(const char *filename, unsigned long *size)
  {
        struct stat st;
        void *map;
        return map;
  }
  
- /*
-    Return a copy of the next line in a mmap'ed file.
-    spaces in the beginning of the line is trimmed away.
-    Return a pointer to a static buffer.
- */
- char*
- get_next_line(unsigned long *pos, void *file, unsigned long size)
+ /**
+   * Return a copy of the next line in a mmap'ed file.
+   * spaces in the beginning of the line is trimmed away.
+   * Return a pointer to a static buffer.
+   **/
+ char* get_next_line(unsigned long *pos, void *file, unsigned long size)
  {
        static char line[4096];
        int skip = 1;
        return NULL;
  }
  
- void
- release_file(void *file, unsigned long size)
+ void release_file(void *file, unsigned long size)
  {
        munmap(file, size);
  }
  
- void
- parse_elf(struct elf_info *info, const char *filename)
+ static void parse_elf(struct elf_info *info, const char *filename)
  {
        unsigned int i;
        Elf_Ehdr *hdr = info->hdr;
                        continue;
  
                info->symtab_start = (void *)hdr + sechdrs[i].sh_offset;
-               info->symtab_stop  = (void *)hdr + sechdrs[i].sh_offset 
+               info->symtab_stop  = (void *)hdr + sechdrs[i].sh_offset
                                                 + sechdrs[i].sh_size;
-               info->strtab       = (void *)hdr + 
+               info->strtab       = (void *)hdr +
                                     sechdrs[sechdrs[i].sh_link].sh_offset;
        }
        if (!info->symtab_start) {
-               fprintf(stderr, "modpost: %s no symtab?\n", filename);
-               abort();
+               fatal("%s has no symtab?\n", filename);
        }
        /* Fix endianness in symbols */
        for (sym = info->symtab_start; sym < info->symtab_stop; sym++) {
        return;
  
   truncated:
-       fprintf(stderr, "modpost: %s is truncated.\n", filename);
-       abort();
+       fatal("%s is truncated.\n", filename);
  }
  
- void
- parse_elf_finish(struct elf_info *info)
+ static void parse_elf_finish(struct elf_info *info)
  {
        release_file(info->hdr, info->size);
  }
  
- #define CRC_PFX     "__crc_"
- #define KSYMTAB_PFX "__ksymtab_"
+ #define CRC_PFX     MODULE_SYMBOL_PREFIX "__crc_"
+ #define KSYMTAB_PFX MODULE_SYMBOL_PREFIX "__ksymtab_"
  
- void
- handle_modversions(struct module *mod, struct elf_info *info,
-                  Elf_Sym *sym, const char *symname)
+ static void handle_modversions(struct module *mod, struct elf_info *info,
+                              Elf_Sym *sym, const char *symname)
  {
        unsigned int crc;
  
        switch (sym->st_shndx) {
        case SHN_COMMON:
-               fprintf(stderr, "*** Warning: \"%s\" [%s] is COMMON symbol\n",
-                       symname, mod->name);
+               warn("\"%s\" [%s] is COMMON symbol\n", symname, mod->name);
                break;
        case SHN_ABS:
                /* CRC'd symbol */
                if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
                        crc = (unsigned int) sym->st_value;
-                       add_exported_symbol(symname + strlen(CRC_PFX),
-                                           mod, &crc);
+                       sym_update_crc(symname + strlen(CRC_PFX), mod, crc);
                }
                break;
        case SHN_UNDEF:
                        /* Ignore register directives. */
                        if (ELF_ST_TYPE(sym->st_info) == STT_SPARC_REGISTER)
                                break;
-                       if (symname[0] == '.') {
-                               char *munged = strdup(symname);
-                               munged[0] = '_';
-                               munged[1] = toupper(munged[1]);
-                               symname = munged;
-                       }
+                       if (symname[0] == '.') {
+                               char *munged = strdup(symname);
+                               munged[0] = '_';
+                               munged[1] = toupper(munged[1]);
+                               symname = munged;
+                       }
                }
  #endif
-               
                if (memcmp(symname, MODULE_SYMBOL_PREFIX,
                           strlen(MODULE_SYMBOL_PREFIX)) == 0)
                        mod->unres = alloc_symbol(symname +
        default:
                /* All exported symbols */
                if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) {
-                       add_exported_symbol(symname + strlen(KSYMTAB_PFX),
-                                           mod, NULL);
+                       sym_add_exported(symname + strlen(KSYMTAB_PFX), mod);
                }
                if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0)
                        mod->has_init = 1;
        }
  }
  
- int
- is_vmlinux(const char *modname)
- {
-       const char *myname;
-       if ((myname = strrchr(modname, '/')))
-               myname++;
-       else
-               myname = modname;
-       return strcmp(myname, "vmlinux") == 0;
- }
- /* Parse tag=value strings from .modinfo section */
+ /**
+  * Parse tag=value strings from .modinfo section
+  **/
  static char *next_string(char *string, unsigned long *secsize)
  {
        /* Skip non-zero chars */
@@@ -446,8 -451,418 +451,418 @@@ static char *get_modinfo(void *modinfo
        return NULL;
  }
  
- void
- read_symbols(char *modname)
+ /**
+  * Test if string s ends in string sub
+  * return 0 if match
+  **/
+ static int strrcmp(const char *s, const char *sub)
+ {
+         int slen, sublen;
+       if (!s || !sub)
+               return 1;
+       slen = strlen(s);
+         sublen = strlen(sub);
+       if ((slen == 0) || (sublen == 0))
+               return 1;
+         if (sublen > slen)
+                 return 1;
+         return memcmp(s + slen - sublen, sub, sublen);
+ }
+ /**
+  * Whitelist to allow certain references to pass with no warning.
+  * Pattern 1:
+  *   If a module parameter is declared __initdata and permissions=0
+  *   then this is legal despite the warning generated.
+  *   We cannot see value of permissions here, so just ignore
+  *   this pattern.
+  *   The pattern is identified by:
+  *   tosec   = .init.data
+  *   fromsec = .data*
+  *   atsym   =__param*
+  *
+  * Pattern 2:
+  *   Many drivers utilise a *_driver container with references to
+  *   add, remove, probe functions etc.
+  *   These functions may often be marked __init and we do not want to
+  *   warn here.
+  *   the pattern is identified by:
+  *   tosec   = .init.text | .exit.text
+  *   fromsec = .data
+  *   atsym = *_driver, *_ops, *_probe, *probe_one
+  **/
+ static int secref_whitelist(const char *tosec, const char *fromsec,
+                         const char *atsym)
+ {
+       int f1 = 1, f2 = 1;
+       const char **s;
+       const char *pat2sym[] = {
+               "_driver",
+               "_ops",
+               "_probe",
+               "_probe_one",
+               NULL
+       };
+       /* Check for pattern 1 */
+       if (strcmp(tosec, ".init.data") != 0)
+               f1 = 0;
+       if (strncmp(fromsec, ".data", strlen(".data")) != 0)
+               f1 = 0;
+       if (strncmp(atsym, "__param", strlen("__param")) != 0)
+               f1 = 0;
+       if (f1)
+               return f1;
+       /* Check for pattern 2 */
+       if ((strcmp(tosec, ".init.text") != 0) &&
+           (strcmp(tosec, ".exit.text") != 0))
+               f2 = 0;
+       if (strcmp(fromsec, ".data") != 0)
+               f2 = 0;
+       for (s = pat2sym; *s; s++)
+               if (strrcmp(atsym, *s) == 0)
+                       f1 = 1;
+       return f1 && f2;
+ }
+ /**
+  * Find symbol based on relocation record info.
+  * In some cases the symbol supplied is a valid symbol so
+  * return refsym. If st_name != 0 we assume this is a valid symbol.
+  * In other cases the symbol needs to be looked up in the symbol table
+  * based on section and address.
+  *  **/
+ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf_Addr addr,
+                               Elf_Sym *relsym)
+ {
+       Elf_Sym *sym;
+       if (relsym->st_name != 0)
+               return relsym;
+       for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
+               if (sym->st_shndx != relsym->st_shndx)
+                       continue;
+               if (sym->st_value == addr)
+                       return sym;
+       }
+       return NULL;
+ }
+ /*
+  * Find symbols before or equal addr and after addr - in the section sec.
+  * If we find two symbols with equal offset prefer one with a valid name.
+  * The ELF format may have a better way to detect what type of symbol
+  * it is, but this works for now.
+  **/
+ static void find_symbols_between(struct elf_info *elf, Elf_Addr addr,
+                                const char *sec,
+                                Elf_Sym **before, Elf_Sym **after)
+ {
+       Elf_Sym *sym;
+       Elf_Ehdr *hdr = elf->hdr;
+       Elf_Addr beforediff = ~0;
+       Elf_Addr afterdiff = ~0;
+       const char *secstrings = (void *)hdr +
+                                elf->sechdrs[hdr->e_shstrndx].sh_offset;
+       *before = NULL;
+       *after = NULL;
+       for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
+               const char *symsec;
+               if (sym->st_shndx >= SHN_LORESERVE)
+                       continue;
+               symsec = secstrings + elf->sechdrs[sym->st_shndx].sh_name;
+               if (strcmp(symsec, sec) != 0)
+                       continue;
+               if (sym->st_value <= addr) {
+                       if ((addr - sym->st_value) < beforediff) {
+                               beforediff = addr - sym->st_value;
+                               *before = sym;
+                       }
+                       else if ((addr - sym->st_value) == beforediff) {
+                               /* equal offset, valid name? */
+                               const char *name = elf->strtab + sym->st_name;
+                               if (name && strlen(name))
+                                       *before = sym;
+                       }
+               }
+               else
+               {
+                       if ((sym->st_value - addr) < afterdiff) {
+                               afterdiff = sym->st_value - addr;
+                               *after = sym;
+                       }
+                       else if ((sym->st_value - addr) == afterdiff) {
+                               /* equal offset, valid name? */
+                               const char *name = elf->strtab + sym->st_name;
+                               if (name && strlen(name))
+                                       *after = sym;
+                       }
+               }
+       }
+ }
+ /**
+  * Print a warning about a section mismatch.
+  * Try to find symbols near it so user can find it.
+  * Check whitelist before warning - it may be a false positive.
+  **/
+ static void warn_sec_mismatch(const char *modname, const char *fromsec,
+                             struct elf_info *elf, Elf_Sym *sym, Elf_Rela r)
+ {
+       const char *refsymname = "";
+       Elf_Sym *before, *after;
+       Elf_Sym *refsym;
+       Elf_Ehdr *hdr = elf->hdr;
+       Elf_Shdr *sechdrs = elf->sechdrs;
+       const char *secstrings = (void *)hdr +
+                                sechdrs[hdr->e_shstrndx].sh_offset;
+       const char *secname = secstrings + sechdrs[sym->st_shndx].sh_name;
+       find_symbols_between(elf, r.r_offset, fromsec, &before, &after);
+       refsym = find_elf_symbol(elf, r.r_addend, sym);
+       if (refsym && strlen(elf->strtab + refsym->st_name))
+               refsymname = elf->strtab + refsym->st_name;
+       /* check whitelist - we may ignore it */
+       if (before &&
+           secref_whitelist(secname, fromsec, elf->strtab + before->st_name))
+               return;
+       if (before && after) {
+               warn("%s - Section mismatch: reference to %s:%s from %s "
+                    "between '%s' (at offset 0x%llx) and '%s'\n",
+                    modname, secname, refsymname, fromsec,
+                    elf->strtab + before->st_name,
+                    (long long)r.r_offset,
+                    elf->strtab + after->st_name);
+       } else if (before) {
+               warn("%s - Section mismatch: reference to %s:%s from %s "
+                    "after '%s' (at offset 0x%llx)\n",
+                    modname, secname, refsymname, fromsec,
+                    elf->strtab + before->st_name,
+                    (long long)r.r_offset);
+       } else if (after) {
+               warn("%s - Section mismatch: reference to %s:%s from %s "
+                    "before '%s' (at offset -0x%llx)\n",
+                    modname, secname, refsymname, fromsec,
+                    elf->strtab + before->st_name,
+                    (long long)r.r_offset);
+       } else {
+               warn("%s - Section mismatch: reference to %s:%s from %s "
+                    "(offset 0x%llx)\n",
+                    modname, secname, fromsec, refsymname,
+                    (long long)r.r_offset);
+       }
+ }
+ /**
+  * A module includes a number of sections that are discarded
+  * either when loaded or when used as built-in.
+  * For loaded modules all functions marked __init and all data
+  * marked __initdata will be discarded when the module has been intialized.
+  * Likewise for modules used built-in the sections marked __exit
+  * are discarded because __exit marked function are supposed to be called
+  * only when a moduel is unloaded which never happes for built-in modules.
+  * The check_sec_ref() function traverses all relocation records
+  * to find all references to a section that reference a section that will
+  * be discarded and warns about it.
+  **/
+ static void check_sec_ref(struct module *mod, const char *modname,
+                         struct elf_info *elf,
+                         int section(const char*),
+                         int section_ref_ok(const char *))
+ {
+       int i;
+       Elf_Sym  *sym;
+       Elf_Ehdr *hdr = elf->hdr;
+       Elf_Shdr *sechdrs = elf->sechdrs;
+       const char *secstrings = (void *)hdr +
+                                sechdrs[hdr->e_shstrndx].sh_offset;
+       /* Walk through all sections */
+       for (i = 0; i < hdr->e_shnum; i++) {
+               Elf_Rela *rela;
+               Elf_Rela *start = (void *)hdr + sechdrs[i].sh_offset;
+               Elf_Rela *stop  = (void*)start + sechdrs[i].sh_size;
+               const char *name = secstrings + sechdrs[i].sh_name +
+                                               strlen(".rela");
+               /* We want to process only relocation sections and not .init */
+               if (section_ref_ok(name) || (sechdrs[i].sh_type != SHT_RELA))
+                       continue;
+               for (rela = start; rela < stop; rela++) {
+                       Elf_Rela r;
+                       const char *secname;
+                       r.r_offset = TO_NATIVE(rela->r_offset);
+                       r.r_info   = TO_NATIVE(rela->r_info);
+                       r.r_addend = TO_NATIVE(rela->r_addend);
+                       sym = elf->symtab_start + ELF_R_SYM(r.r_info);
+                       /* Skip special sections */
+                       if (sym->st_shndx >= SHN_LORESERVE)
+                               continue;
+                       secname = secstrings + sechdrs[sym->st_shndx].sh_name;
+                       if (section(secname))
+                               warn_sec_mismatch(modname, name, elf, sym, r);
+               }
+       }
+ }
+ /**
+  * Functions used only during module init is marked __init and is stored in
+  * a .init.text section. Likewise data is marked __initdata and stored in
+  * a .init.data section.
+  * If this section is one of these sections return 1
+  * See include/linux/init.h for the details
+  **/
+ static int init_section(const char *name)
+ {
+       if (strcmp(name, ".init") == 0)
+               return 1;
+       if (strncmp(name, ".init.", strlen(".init.")) == 0)
+               return 1;
+       return 0;
+ }
+ /**
+  * Identify sections from which references to a .init section is OK.
+  *
+  * Unfortunately references to read only data that referenced .init
+  * sections had to be excluded. Almost all of these are false
+  * positives, they are created by gcc. The downside of excluding rodata
+  * is that there really are some user references from rodata to
+  * init code, e.g. drivers/video/vgacon.c:
+  *
+  * const struct consw vga_con = {
+  *        con_startup:            vgacon_startup,
+  *
+  * where vgacon_startup is __init.  If you want to wade through the false
+  * positives, take out the check for rodata.
+  **/
+ static int init_section_ref_ok(const char *name)
+ {
+       const char **s;
+       /* Absolute section names */
+       const char *namelist1[] = {
+               ".init",
+               ".opd",   /* see comment [OPD] at exit_section_ref_ok() */
+               ".toc1",  /* used by ppc64 */
+               ".stab",
+               ".rodata",
+               ".text.lock",
+               "__bug_table", /* used by powerpc for BUG() */
+               ".pci_fixup_header",
+               ".pci_fixup_final",
+               ".pdr",
+               "__param",
+               NULL
+       };
+       /* Start of section names */
+       const char *namelist2[] = {
+               ".init.",
+               ".altinstructions",
+               ".eh_frame",
+               ".debug",
+               NULL
+       };
+       /* part of section name */
+       const char *namelist3 [] = {
+               ".unwind",  /* sample: IA_64.unwind.init.text */
+               NULL
+       };
+       for (s = namelist1; *s; s++)
+               if (strcmp(*s, name) == 0)
+                       return 1;
+       for (s = namelist2; *s; s++)
+               if (strncmp(*s, name, strlen(*s)) == 0)
+                       return 1;
+       for (s = namelist3; *s; s++)
+               if (strstr(name, *s) != NULL)
+                       return 1;
+       return 0;
+ }
+ /*
+  * Functions used only during module exit is marked __exit and is stored in
+  * a .exit.text section. Likewise data is marked __exitdata and stored in
+  * a .exit.data section.
+  * If this section is one of these sections return 1
+  * See include/linux/init.h for the details
+  **/
+ static int exit_section(const char *name)
+ {
+       if (strcmp(name, ".exit.text") == 0)
+               return 1;
+       if (strcmp(name, ".exit.data") == 0)
+               return 1;
+       return 0;
+ }
+ /*
+  * Identify sections from which references to a .exit section is OK.
+  *
+  * [OPD] Keith Ownes <kaos@sgi.com> commented:
+  * For our future {in}sanity, add a comment that this is the ppc .opd
+  * section, not the ia64 .opd section.
+  * ia64 .opd should not point to discarded sections.
+  **/
+ static int exit_section_ref_ok(const char *name)
+ {
+       const char **s;
+       /* Absolute section names */
+       const char *namelist1[] = {
+               ".exit.text",
+               ".exit.data",
+               ".init.text",
+               ".opd", /* See comment [OPD] */
+               ".toc1",  /* used by ppc64 */
+               ".altinstructions",
+               ".pdr",
+               "__bug_table", /* used by powerpc for BUG() */
+               ".exitcall.exit",
+               ".eh_frame",
+               ".stab",
+               NULL
+       };
+       /* Start of section names */
+       const char *namelist2[] = {
+               ".debug",
+               NULL
+       };
+       /* part of section name */
+       const char *namelist3 [] = {
+               ".unwind",  /* Sample: IA_64.unwind.exit.text */
+               NULL
+       };
+       for (s = namelist1; *s; s++)
+               if (strcmp(*s, name) == 0)
+                       return 1;
+       for (s = namelist2; *s; s++)
+               if (strncmp(*s, name, strlen(*s)) == 0)
+                       return 1;
+       for (s = namelist3; *s; s++)
+               if (strstr(name, *s) != NULL)
+                       return 1;
+       return 0;
+ }
+ static void read_symbols(char *modname)
  {
        const char *symname;
        char *version;
        /* When there's no vmlinux, don't print warnings about
         * unresolved symbols (since there'll be too many ;) */
        if (is_vmlinux(modname)) {
-               unsigned int fake_crc = 0;
                have_vmlinux = 1;
-               add_exported_symbol("struct_module", mod, &fake_crc);
                mod->skip = 1;
        }
  
                handle_modversions(mod, &info, sym, symname);
                handle_moddevtable(mod, &info, sym, symname);
        }
+       check_sec_ref(mod, modname, &info, init_section, init_section_ref_ok);
+       check_sec_ref(mod, modname, &info, exit_section, exit_section_ref_ok);
  
        version = get_modinfo(info.modinfo, info.modinfo_len, "version");
        if (version)
   * following helper, then compare to the file on disk and
   * only update the later if anything changed */
  
- void __attribute__((format(printf, 2, 3)))
buf_printf(struct buffer *buf, const char *fmt, ...)
+ void __attribute__((format(printf, 2, 3))) buf_printf(struct buffer *buf,
                                                    const char *fmt, ...)
  {
        char tmp[SZ];
        int len;
        va_list ap;
-       
        va_start(ap, fmt);
        len = vsnprintf(tmp, SZ, fmt, ap);
 -      if (buf->size - buf->pos < len + 1) {
 -              buf->size += 128;
 -              buf->p = realloc(buf->p, buf->size);
 -      }
 -      strncpy(buf->p + buf->pos, tmp, len + 1);
 -      buf->pos += len;
 +      buf_write(buf, tmp, len);
        va_end(ap);
  }
  
- void
- buf_write(struct buffer *buf, const char *s, int len)
+ void buf_write(struct buffer *buf, const char *s, int len)
  {
        if (buf->size - buf->pos < len) {
 -              buf->size += len;
 +              buf->size += len + SZ;
                buf->p = realloc(buf->p, buf->size);
        }
        strncpy(buf->p + buf->pos, s, len);
        buf->pos += len;
  }
  
- /* Header for the generated file */
- void
- add_header(struct buffer *b, struct module *mod)
+ /**
+  * Header for the generated file
+  **/
static void add_header(struct buffer *b, struct module *mod)
  {
        buf_printf(b, "#include <linux/module.h>\n");
        buf_printf(b, "#include <linux/vermagic.h>\n");
        buf_printf(b, "};\n");
  }
  
- /* Record CRCs for unresolved symbols */
- void
- add_versions(struct buffer *b, struct module *mod)
+ /**
+  * Record CRCs for unresolved symbols
+  **/
static void add_versions(struct buffer *b, struct module *mod)
  {
        struct symbol *s, *exp;
  
                exp = find_symbol(s->name);
                if (!exp || exp->module == mod) {
                        if (have_vmlinux && !s->weak)
-                               fprintf(stderr, "*** Warning: \"%s\" [%s.ko] "
-                               "undefined!\n", s->name, mod->name);
+                               warn("\"%s\" [%s.ko] undefined!\n",
+                                    s->name, mod->name);
                        continue;
                }
                s->module = exp->module;
                        continue;
                }
                if (!s->crc_valid) {
-                       fprintf(stderr, "*** Warning: \"%s\" [%s.ko] "
-                               "has no CRC!\n",
+                       warn("\"%s\" [%s.ko] has no CRC!\n",
                                s->name, mod->name);
                        continue;
                }
        buf_printf(b, "};\n");
  }
  
- void
add_depends(struct buffer *b, struct module *mod, struct module *modules)
+ static void add_depends(struct buffer *b, struct module *mod,
                      struct module *modules)
  {
        struct symbol *s;
        struct module *m;
        buf_printf(b, "\";\n");
  }
  
- void
- add_srcversion(struct buffer *b, struct module *mod)
+ static void add_srcversion(struct buffer *b, struct module *mod)
  {
        if (mod->srcversion[0]) {
                buf_printf(b, "\n");
        }
  }
  
- void
- write_if_changed(struct buffer *b, const char *fname)
+ static void write_if_changed(struct buffer *b, const char *fname)
  {
        char *tmp;
        FILE *file;
        fclose(file);
  }
  
- void
- read_dump(const char *fname)
+ static void read_dump(const char *fname, unsigned int kernel)
  {
        unsigned long size, pos = 0;
        void *file = grab_file(fname, &size);
                char *symname, *modname, *d;
                unsigned int crc;
                struct module *mod;
+               struct symbol *s;
  
                if (!(symname = strchr(line, '\t')))
                        goto fail;
                        mod = new_module(NOFAIL(strdup(modname)));
                        mod->skip = 1;
                }
-               add_exported_symbol(symname, mod, &crc);
+               s = sym_add_exported(symname, mod);
+               s->kernel    = kernel;
+               s->preloaded = 1;
+               sym_update_crc(symname, mod, crc);
        }
        return;
  fail:
        fatal("parse error in symbol dump file\n");
  }
  
- void
- write_dump(const char *fname)
+ /* For normal builds always dump all symbols.
+  * For external modules only dump symbols
+  * that are not read from kernel Module.symvers.
+  **/
+ static int dump_sym(struct symbol *sym)
+ {
+       if (!external_module)
+               return 1;
+       if (sym->vmlinux || sym->kernel)
+               return 0;
+       return 1;
+ }
+ static void write_dump(const char *fname)
  {
        struct buffer buf = { };
        struct symbol *symbol;
        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);
+                       if (dump_sym(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
- main(int argc, char **argv)
+ int main(int argc, char **argv)
  {
        struct module *mod;
        struct buffer buf = { };
        char fname[SZ];
-       char *dump_read = NULL, *dump_write = NULL;
+       char *kernel_read = NULL, *module_read = NULL;
+       char *dump_write = NULL;
        int opt;
  
-       while ((opt = getopt(argc, argv, "i:mo:a")) != -1) {
+       while ((opt = getopt(argc, argv, "i:I:mo:a")) != -1) {
                switch(opt) {
                        case 'i':
-                               dump_read = optarg;
+                               kernel_read = optarg;
+                               break;
+                       case 'I':
+                               module_read = optarg;
+                               external_module = 1;
                                break;
                        case 'm':
                                modversions = 1;
                }
        }
  
-       if (dump_read)
-               read_dump(dump_read);
+       if (kernel_read)
+               read_dump(kernel_read, 1);
+       if (module_read)
+               read_dump(module_read, 0);
  
        while (optind < argc) {
                read_symbols(argv[optind++]);
  
        return 0;
  }