Merge git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild-next
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 28 Dec 2008 23:13:48 +0000 (15:13 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 28 Dec 2008 23:13:48 +0000 (15:13 -0800)
* git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild-next: (25 commits)
  allow stripping of generated symbols under CONFIG_KALLSYMS_ALL
  kbuild: strip generated symbols from *.ko
  kbuild: simplify use of genksyms
  kernel-doc: check for extra kernel-doc notations
  kbuild: add headerdep used to detect inclusion cycles in header files
  kbuild: fix string equality testing in tags.sh
  kbuild: fix make tags/cscope
  kbuild: fix make incompatibility
  kbuild: remove TAR_IGNORE
  setlocalversion: add git-svn support
  setlocalversion: print correct subversion revision
  scripts: improve the decodecode script
  scripts/package: allow custom options to rpm
  genksyms: allow to ignore symbol checksum changes
  genksyms: track symbol checksum changes
  tags and cscope support really belongs in a shell script
  kconfig: fix options to check-lxdialog.sh
  kbuild: gen_init_cpio expands shell variables in file names
  remove bashisms from scripts/extract-ikconfig
  kbuild: teach mkmakfile to be silent
  ...

28 files changed:
Documentation/kbuild/makefiles.txt
Makefile
arch/blackfin/boot/Makefile
arch/x86/scripts/strip-symbols [new file with mode: 0644]
init/Kconfig
kernel/kallsyms.c
scripts/Kbuild.include
scripts/Makefile.build
scripts/Makefile.lib
scripts/Makefile.modinst
scripts/decodecode
scripts/extract-ikconfig
scripts/genksyms/genksyms.c
scripts/genksyms/genksyms.h
scripts/genksyms/keywords.c_shipped
scripts/genksyms/keywords.gperf
scripts/headerdep.pl [new file with mode: 0755]
scripts/kallsyms.c
scripts/kconfig/lxdialog/check-lxdialog.sh
scripts/kernel-doc
scripts/mkcompile_h
scripts/mkmakefile
scripts/mksysmap
scripts/package/Makefile
scripts/setlocalversion
scripts/strip-symbols [new file with mode: 0644]
scripts/tags.sh [new file with mode: 0755]
usr/gen_init_cpio.c

index 7a77533..51104f9 100644 (file)
@@ -383,6 +383,20 @@ more details, with real examples.
        to prerequisites are referenced with $(src) (because they are not
        generated files).
 
+    $(kecho)
+       echoing information to user in a rule is often a good practice
+       but when execution "make -s" one does not expect to see any output
+       except for warnings/errors.
+       To support this kbuild define $(kecho) which will echo out the
+       text following $(kecho) to stdout except if "make -s" is used.
+
+       Example:
+               #arch/blackfin/boot/Makefile
+               $(obj)/vmImage: $(obj)/vmlinux.gz
+                       $(call if_changed,uimage)
+                       @$(kecho) 'Kernel: $@ is ready'
+
+
 --- 3.11 $(CC) support functions
 
        The kernel may be built with several different versions of
index 71e98e9..09ff7d8 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -336,7 +336,7 @@ LINUXINCLUDE    := -Iinclude \
                    -I$(srctree)/arch/$(hdr-arch)/include               \
                    -include include/linux/autoconf.h
 
-KBUILD_CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
+KBUILD_CPPFLAGS := -D__KERNEL__
 
 KBUILD_CFLAGS   := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
                   -fno-strict-aliasing -fno-common \
@@ -439,7 +439,11 @@ ifeq ($(config-targets),1)
 include $(srctree)/arch/$(SRCARCH)/Makefile
 export KBUILD_DEFCONFIG KBUILD_KCONFIG
 
-config %config: scripts_basic outputmakefile FORCE
+config: scripts_basic outputmakefile FORCE
+       $(Q)mkdir -p include/linux include/config
+       $(Q)$(MAKE) $(build)=scripts/kconfig $@
+
+%config: scripts_basic outputmakefile FORCE
        $(Q)mkdir -p include/linux include/config
        $(Q)$(MAKE) $(build)=scripts/kconfig $@
 
@@ -600,20 +604,25 @@ export    INSTALL_PATH ?= /boot
 MODLIB = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
 export MODLIB
 
-#
-#  INSTALL_MOD_STRIP, if defined, will cause modules to be
-#  stripped after they are installed.  If INSTALL_MOD_STRIP is '1', then
-#  the default option --strip-debug will be used.  Otherwise,
-#  INSTALL_MOD_STRIP will used as the options to the strip command.
+strip-symbols := $(srctree)/scripts/strip-symbols \
+                $(wildcard $(srctree)/arch/$(ARCH)/scripts/strip-symbols)
 
+#
+# INSTALL_MOD_STRIP, if defined, will cause modules to be stripped while
+# they get installed.  If INSTALL_MOD_STRIP is '1', then the default
+# options (see below) will be used.  Otherwise, INSTALL_MOD_STRIP will
+# be used as the option(s) to the objcopy command.
 ifdef INSTALL_MOD_STRIP
 ifeq ($(INSTALL_MOD_STRIP),1)
-mod_strip_cmd = $(STRIP) --strip-debug
+mod_strip_cmd = $(OBJCOPY) --strip-debug
+ifeq ($(CONFIG_KALLSYMS_ALL),$(CONFIG_KALLSYMS_STRIP_GENERATED))
+mod_strip_cmd += --wildcard $(addprefix --strip-symbols ,$(strip-symbols))
+endif
 else
-mod_strip_cmd = $(STRIP) $(INSTALL_MOD_STRIP)
+mod_strip_cmd = $(OBJCOPY) $(INSTALL_MOD_STRIP)
 endif # INSTALL_MOD_STRIP=1
 else
-mod_strip_cmd = true
+mod_strip_cmd = false
 endif # INSTALL_MOD_STRIP
 export mod_strip_cmd
 
@@ -743,6 +752,7 @@ last_kallsyms := 2
 endif
 
 kallsyms.o := .tmp_kallsyms$(last_kallsyms).o
+kallsyms.h := $(wildcard include/config/kallsyms/*.h) $(wildcard include/config/kallsyms/*/*.h)
 
 define verify_kallsyms
        $(Q)$(if $($(quiet)cmd_sysmap),                                      \
@@ -767,24 +777,41 @@ endef
 
 # Generate .S file with all kernel symbols
 quiet_cmd_kallsyms = KSYM    $@
-      cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) \
-                     $(if $(CONFIG_KALLSYMS_ALL),--all-symbols) > $@
+      cmd_kallsyms = { test $* -eq 0 || $(NM) -n $<; } \
+                    | $(KALLSYMS) $(if $(CONFIG_KALLSYMS_ALL),--all-symbols) >$@
 
-.tmp_kallsyms1.o .tmp_kallsyms2.o .tmp_kallsyms3.o: %.o: %.S scripts FORCE
+quiet_cmd_kstrip = STRIP   $@
+      cmd_kstrip = $(OBJCOPY) --wildcard $(addprefix --strip$(if $(CONFIG_RELOCATABLE),-unneeded)-symbols ,$(filter %/scripts/strip-symbols,$^)) $< $@
+
+$(foreach n,0 1 2 3,.tmp_kallsyms$(n).o): KBUILD_AFLAGS += -Wa,--strip-local-absolute
+$(foreach n,0 1 2 3,.tmp_kallsyms$(n).o): %.o: %.S scripts FORCE
        $(call if_changed_dep,as_o_S)
 
-.tmp_kallsyms%.S: .tmp_vmlinux% $(KALLSYMS)
+ifeq ($(CONFIG_KALLSYMS_STRIP_GENERATED),y)
+strip-ext := .stripped
+endif
+
+.tmp_kallsyms%.S: .tmp_vmlinux%$(strip-ext) $(KALLSYMS) $(kallsyms.h)
        $(call cmd,kallsyms)
 
+# make -jN seems to have problems with intermediate files, see bug #3330.
+.SECONDARY: $(foreach n,1 2 3,.tmp_vmlinux$(n).stripped)
+.tmp_vmlinux%.stripped: .tmp_vmlinux% $(strip-symbols) $(kallsyms.h)
+       $(call cmd,kstrip)
+
+ifneq ($(CONFIG_DEBUG_INFO),y)
+.tmp_vmlinux%: LDFLAGS_vmlinux += -S
+endif
 # .tmp_vmlinux1 must be complete except kallsyms, so update vmlinux version
-.tmp_vmlinux1: $(vmlinux-lds) $(vmlinux-all) FORCE
-       $(call if_changed_rule,ksym_ld)
+.tmp_vmlinux%: $(vmlinux-lds) $(vmlinux-all) FORCE
+       $(if $(filter 1,$*),$(call if_changed_rule,ksym_ld),$(call if_changed,vmlinux__))
 
-.tmp_vmlinux2: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms1.o FORCE
-       $(call if_changed,vmlinux__)
+.tmp_vmlinux0$(strip-ext):
+       $(Q)echo "placeholder" >$@
 
-.tmp_vmlinux3: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms2.o FORCE
-       $(call if_changed,vmlinux__)
+.tmp_vmlinux1: .tmp_kallsyms0.o
+.tmp_vmlinux2: .tmp_kallsyms1.o
+.tmp_vmlinux3: .tmp_kallsyms2.o
 
 # Needs to visit scripts/ before $(KALLSYMS) can be used.
 $(KALLSYMS): scripts ;
@@ -926,7 +953,7 @@ PHONY += prepare archprepare prepare0 prepare1 prepare2 prepare3
 # 2) Create the include2 directory, used for the second asm symlink
 prepare3: include/config/kernel.release
 ifneq ($(KBUILD_SRC),)
-       @echo '  Using $(srctree) as source for kernel'
+       @$(kecho) '  Using $(srctree) as source for kernel'
        $(Q)if [ -f $(srctree)/.config -o -d $(srctree)/include/config ]; then \
                echo "  $(srctree) is not clean, please run 'make mrproper'";\
                echo "  in the '$(srctree)' directory.";\
@@ -983,7 +1010,7 @@ endef
 # directory for generated filesas used by some architectures.
 define create-symlink
        if [ ! -L include/asm ]; then                                      \
-                       echo '  SYMLINK $@ -> include/asm-$(SRCARCH)';     \
+                       $(kecho) '  SYMLINK $@ -> include/asm-$(SRCARCH)'; \
                        if [ ! -d include/asm-$(SRCARCH) ]; then           \
                                mkdir -p include/asm-$(SRCARCH);           \
                        fi;                                                \
@@ -1022,6 +1049,10 @@ include/linux/version.h: $(srctree)/Makefile FORCE
 include/linux/utsrelease.h: include/config/kernel.release FORCE
        $(call filechk,utsrelease.h)
 
+PHONY += headerdep
+headerdep:
+       $(Q)find include/ -name '*.h' | xargs --max-args 1 scripts/headerdep.pl
+
 # ---------------------------------------------------------------------------
 
 PHONY += depend dep
@@ -1096,7 +1127,7 @@ all: modules
 PHONY += modules
 modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux)
        $(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order
-       @echo '  Building modules, stage 2.';
+       @$(kecho) '  Building modules, stage 2.';
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modbuild
 
@@ -1270,7 +1301,8 @@ help:
        @echo  '  versioncheck    - Sanity check on version.h usage'
        @echo  '  includecheck    - Check for duplicate included header files'
        @echo  '  export_report   - List the usages of all exported symbols'
-       @echo  '  headers_check   - Sanity check on exported headers'; \
+       @echo  '  headers_check   - Sanity check on exported headers'
+       @echo  '  headerdep       - Detect inclusion cycles in headers'; \
         echo  ''
        @echo  'Kernel packaging:'
        @$(MAKE) $(build)=$(package-dir) help
@@ -1360,7 +1392,7 @@ $(module-dirs): crmodverdir $(objtree)/Module.symvers
        $(Q)$(MAKE) $(build)=$(patsubst _module_%,%,$@)
 
 modules: $(module-dirs)
-       @echo '  Building modules, stage 2.';
+       @$(kecho) '  Building modules, stage 2.';
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
 
 PHONY += modules_install
@@ -1409,123 +1441,12 @@ endif # KBUILD_EXTMOD
 
 # Generate tags for editors
 # ---------------------------------------------------------------------------
+quiet_cmd_tags = GEN     $@
+      cmd_tags = $(CONFIG_SHELL) $(srctree)/scripts/tags.sh $@
 
-#We want __srctree to totally vanish out when KBUILD_OUTPUT is not set
-#(which is the most common case IMHO) to avoid unneeded clutter in the big tags file.
-#Adding $(srctree) adds about 20M on i386 to the size of the output file!
-
-ifeq ($(src),$(obj))
-__srctree =
-else
-__srctree = $(srctree)/
-endif
-
-ifeq ($(ALLSOURCE_ARCHS),)
-ifeq ($(ARCH),um)
-ALLINCLUDE_ARCHS := $(ARCH) $(SUBARCH)
-else
-ALLINCLUDE_ARCHS := $(SRCARCH)
-endif
-else
-#Allow user to specify only ALLSOURCE_PATHS on the command line, keeping existing behaviour.
-ALLINCLUDE_ARCHS := $(ALLSOURCE_ARCHS)
-endif
-
-ALLSOURCE_ARCHS := $(SRCARCH)
-
-define find-sources
-        ( for arch in $(ALLSOURCE_ARCHS) ; do \
-              find $(__srctree)arch/$${arch} $(RCS_FIND_IGNORE) \
-                   -wholename $(__srctree)arch/$${arch}/include/asm -type d -prune \
-                   -o -name $1 -print; \
-         done ; \
-         find $(__srctree)security/selinux/include $(RCS_FIND_IGNORE) \
-              -name $1 -print; \
-         find $(__srctree)include $(RCS_FIND_IGNORE) \
-              \( -name config -o -name 'asm-*' \) -prune \
-              -o -name $1 -print; \
-         for arch in $(ALLINCLUDE_ARCHS) ; do \
-              test -e $(__srctree)include/asm-$${arch} && \
-                 find $(__srctree)include/asm-$${arch} $(RCS_FIND_IGNORE) \
-                   -name $1 -print; \
-              test -e $(__srctree)arch/$${arch}/include/asm && \
-                find $(__srctree)arch/$${arch}/include/asm $(RCS_FIND_IGNORE) \
-                   -name $1 -print; \
-         done ; \
-         find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
-              -name $1 -print; \
-         find $(__srctree) $(RCS_FIND_IGNORE) \
-              \( -name include -o -name arch -o -name '.tmp_*' \) -prune -o \
-              -name $1 -print; \
-         )
-endef
-
-define all-sources
-       $(call find-sources,'*.[chS]')
-endef
-define all-kconfigs
-       $(call find-sources,'Kconfig*')
-endef
-define all-defconfigs
-       $(call find-sources,'defconfig')
-endef
-
-define xtags
-       if $1 --version 2>&1 | grep -iq exuberant; then \
-           $(all-sources) | xargs $1 -a \
-               -I __initdata,__exitdata,__acquires,__releases \
-               -I __read_mostly,____cacheline_aligned,____cacheline_aligned_in_smp,____cacheline_internodealigned_in_smp \
-               -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL \
-               --extra=+f --c-kinds=+px \
-               --regex-asm='/^ENTRY\(([^)]*)\).*/\1/'; \
-           $(all-kconfigs) | xargs $1 -a \
-               --langdef=kconfig \
-               --language-force=kconfig \
-               --regex-kconfig='/^[[:blank:]]*(menu|)config[[:blank:]]+([[:alnum:]_]+)/\2/'; \
-           $(all-defconfigs) | xargs -r $1 -a \
-               --langdef=dotconfig \
-               --language-force=dotconfig \
-               --regex-dotconfig='/^#?[[:blank:]]*(CONFIG_[[:alnum:]_]+)/\1/'; \
-       elif $1 --version 2>&1 | grep -iq emacs; then \
-           $(all-sources) | xargs $1 -a; \
-           $(all-kconfigs) | xargs $1 -a \
-               --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/'; \
-           $(all-defconfigs) | xargs -r $1 -a \
-               --regex='/^#?[ \t]?\(CONFIG_[a-zA-Z0-9_]+\)/\1/'; \
-       else \
-           $(all-sources) | xargs $1 -a; \
-       fi
-endef
-
-quiet_cmd_cscope-file = FILELST cscope.files
-      cmd_cscope-file = (echo \-k; echo \-q; $(all-sources)) > cscope.files
-
-quiet_cmd_cscope = MAKE    cscope.out
-      cmd_cscope = cscope -b -f cscope.out
-
-cscope: FORCE
-       $(call cmd,cscope-file)
-       $(call cmd,cscope)
-
-quiet_cmd_TAGS = MAKE   $@
-define cmd_TAGS
-       rm -f $@; \
-       $(call xtags,etags)
-endef
-
-TAGS: FORCE
-       $(call cmd,TAGS)
-
-quiet_cmd_tags = MAKE   $@
-define cmd_tags
-       rm -f $@; \
-       $(call xtags,ctags)
-endef
-
-tags: FORCE
+tags TAGS cscope: FORCE
        $(call cmd,tags)
 
-
 # Scripts to check various things for consistency
 # ---------------------------------------------------------------------------
 
@@ -1604,7 +1525,11 @@ endif
        $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
 
 # Modules
-/ %/: prepare scripts FORCE
+/: prepare scripts FORCE
+       $(cmd_crmodverdir)
+       $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
+       $(build)=$(build-dir)
+%/: prepare scripts FORCE
        $(cmd_crmodverdir)
        $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
        $(build)=$(build-dir)
@@ -1638,7 +1563,7 @@ cmd_crmodverdir = $(Q)mkdir -p $(MODVERDIR) \
                   $(if $(KBUILD_MODULES),; rm -f $(MODVERDIR)/*)
 
 a_flags = -Wp,-MD,$(depfile) $(KBUILD_AFLAGS) $(AFLAGS_KERNEL) \
-         $(NOSTDINC_FLAGS) $(KBUILD_CPPFLAGS) \
+         $(NOSTDINC_FLAGS) $(LINUXINCLUDE) $(KBUILD_CPPFLAGS) \
          $(modkern_aflags) $(EXTRA_AFLAGS) $(AFLAGS_$(basetarget).o)
 
 quiet_cmd_as_o_S = AS      $@
index 522f3c1..e028d13 100644 (file)
@@ -25,7 +25,7 @@ $(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE
 
 $(obj)/vmImage: $(obj)/vmlinux.gz
        $(call if_changed,uimage)
-       @echo 'Kernel: $@ is ready'
+       @$(kecho) 'Kernel: $@ is ready'
 
 install:
        sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)"
diff --git a/arch/x86/scripts/strip-symbols b/arch/x86/scripts/strip-symbols
new file mode 100644 (file)
index 0000000..a2f1ccb
--- /dev/null
@@ -0,0 +1 @@
+__cpu_vendor_dev_X86_VENDOR_*
index f291f08..8a63c40 100644 (file)
@@ -588,6 +588,13 @@ config KALLSYMS_ALL
 
           Say N.
 
+config KALLSYMS_STRIP_GENERATED
+       bool "Strip machine generated symbols from kallsyms"
+       depends on KALLSYMS_ALL
+       default y
+       help
+         Say N if you want kallsyms to retain even machine generated symbols.
+
 config KALLSYMS_EXTRA_PASS
        bool "Do an extra kallsyms pass"
        depends on KALLSYMS
index 7b8b0f2..e694afa 100644 (file)
 #define all_var 0
 #endif
 
-/* These will be re-linked against their real values during the second link stage */
-extern const unsigned long kallsyms_addresses[] __attribute__((weak));
-extern const u8 kallsyms_names[] __attribute__((weak));
+extern const unsigned long kallsyms_addresses[];
+extern const u8 kallsyms_names[];
 
 /* tell the compiler that the count isn't in the small data section if the arch
  * has one (eg: FRV)
  */
 extern const unsigned long kallsyms_num_syms
-__attribute__((weak, section(".rodata")));
+       __attribute__((__section__(".rodata")));
 
-extern const u8 kallsyms_token_table[] __attribute__((weak));
-extern const u16 kallsyms_token_index[] __attribute__((weak));
+extern const u8 kallsyms_token_table[];
+extern const u16 kallsyms_token_index[];
 
-extern const unsigned long kallsyms_markers[] __attribute__((weak));
+extern const unsigned long kallsyms_markers[];
 
 static inline int is_kernel_inittext(unsigned long addr)
 {
@@ -168,9 +167,6 @@ static unsigned long get_symbol_pos(unsigned long addr,
        unsigned long symbol_start = 0, symbol_end = 0;
        unsigned long i, low, high, mid;
 
-       /* This kernel should never had been booted. */
-       BUG_ON(!kallsyms_addresses);
-
        /* do a binary search on the sorted kallsyms_addresses array */
        low = 0;
        high = kallsyms_num_syms;
index 982dcae..c29be8f 100644 (file)
@@ -24,6 +24,13 @@ basetarget = $(basename $(notdir $@))
 # Escape single quote for use in echo statements
 escsq = $(subst $(squote),'\$(squote)',$1)
 
+###
+# Easy method for doing a status message
+       kecho := :
+ quiet_kecho := echo
+silent_kecho := :
+kecho := $($(quiet)kecho)
+
 ###
 # filechk is used to check if the content of a generated file is updated.
 # Sample usage:
@@ -39,22 +46,15 @@ escsq = $(subst $(squote),'\$(squote)',$1)
 # - If they are equal no change, and no timestamp update
 # - stdin is piped in from the first prerequisite ($<) so one has
 #   to specify a valid file as first prerequisite (often the kbuild file)
-       chk_filechk = :
- quiet_chk_filechk = echo '  CHK     $@'
-silent_chk_filechk = :
-       upd_filechk = :
- quiet_upd_filechk = echo '  UPD     $@'
-silent_upd_filechk = :
-
 define filechk
        $(Q)set -e;                             \
-       $($(quiet)chk_filechk);                 \
+       $(kecho) '  CHK     $@';                \
        mkdir -p $(dir $@);                     \
        $(filechk_$(1)) < $< > $@.tmp;          \
        if [ -r $@ ] && cmp -s $@ $@.tmp; then  \
                rm -f $@.tmp;                   \
        else                                    \
-               $($(quiet)upd_filechk);         \
+               $(kecho) '  UPD     $@';        \
                mv -f $@.tmp $@;                \
        fi
 endef
@@ -144,7 +144,9 @@ ld-option = $(call try-run,\
 build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
 
 # Prefix -I with $(srctree) if it is not an absolute path.
-addtree = $(if $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1)
+# skip if -I has no parameter
+addtree = $(if $(patsubst -I%,%,$(1)), \
+$(if $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1))
 
 # Find all -I options and call addtree
 flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o)))
index 7a17677..5d90030 100644 (file)
@@ -151,14 +151,20 @@ cmd_cc_i_c       = $(CPP) $(c_flags)   -o $@ $<
 $(obj)/%.i: $(src)/%.c FORCE
        $(call if_changed_dep,cc_i_c)
 
+cmd_genksyms =                                                              \
+    $(CPP) -D__GENKSYMS__ $(c_flags) $< |                                   \
+    $(GENKSYMS) -T $@ -A -a $(ARCH)                                         \
+     $(if $(KBUILD_PRESERVE),-p)                                            \
+     $(if $(1),-r $(firstword $(wildcard $(@:.symtypes=.symref) /dev/null)))
+
 quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@
-cmd_cc_symtypes_c         = \
-               $(CPP) -D__GENKSYMS__ $(c_flags) $<                     \
-               | $(GENKSYMS) -T $@ >/dev/null;                         \
-               test -s $@ || rm -f $@
+cmd_cc_symtypes_c =                                                         \
+    set -e;                                                                 \
+    $(call cmd_genksyms, true) >/dev/null;                                  \
+    test -s $@ || rm -f $@
 
 $(obj)/%.symtypes : $(src)/%.c FORCE
-       $(call if_changed_dep,cc_symtypes_c)
+       $(call cmd,cc_symtypes_c)
 
 # C (.c) files
 # The C file is compiled and updated dependency information is generated.
@@ -171,30 +177,38 @@ cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
 
 else
 # When module versioning is enabled the following steps are executed:
-# 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
+# o compile a .tmp_<file>.s from <file>.c
+# o if .tmp_<file>.s doesn't contain a __ksymtab version, i.e. does
+#   not export symbols, we just assemble .tmp_<file>.s 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
+#   that they are usable as assembly source
+# o assemble <file>.o from .tmp_<file>.s forcing inclusion of directives
+#   defining the actual values of __crc_*, followed by objcopy-ing them
+#   to force these symbols to be local to permit stripping them later.
+s_file = $(@D)/.tmp_$(@F:.o=.s)
+v_file = $(@D)/.tmp_$(@F:.o=.v)
+tmp_o_file = $(@D)/.tmp_$(@F)
+no_g_c_flags = $(filter-out -g%,$(c_flags))
+
+cmd_cc_o_c = $(CC) $(c_flags) -S -o $(s_file) $<
 
-cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $<
 cmd_modversions =                                                      \
-       if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then     \
-               $(CPP) -D__GENKSYMS__ $(c_flags) $<                     \
-               | $(GENKSYMS) $(if $(KBUILD_SYMTYPES),                  \
-                             -T $(@D)/$(@F:.o=.symtypes)) -a $(ARCH)   \
-               > $(@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);        \
+       if grep -q __ksymtab $(s_file); then                            \
+               if $(call cmd_genksyms, $(KBUILD_SYMTYPES)) > $(v_file) \
+                  && $(CC) $(no_g_c_flags) -c -Wa,$(v_file)            \
+                           -o $(tmp_o_file) $(s_file)                  \
+                  && $(OBJCOPY) -L '__crc_*' -L '___crc_*' -w          \
+                                $(tmp_o_file) $@;                      \
+               then                                                    \
+                       : ;                                             \
+               else                                                    \
+                       rm -f $@; exit 1;                               \
+               fi;                                                     \
        else                                                            \
-               mv -f $(@D)/.tmp_$(@F) $@;                              \
+               rm -f $(v_file);                                        \
+               $(CC) $(no_g_c_flags) -c -o $@ $(s_file);               \
        fi;
 endif
 
@@ -211,7 +225,12 @@ define rule_cc_o_c
        $(cmd_record_mcount)                                              \
        scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' >    \
                                                      $(dot-target).tmp;  \
-       rm -f $(depfile);                                                 \
+       if [ -r $(@D)/.tmp_$(@F:.o=.v) ]; then                            \
+               echo >> $(dot-target).tmp;                                \
+               echo '$@: $(GENKSYMS)' >> $(dot-target).tmp;              \
+               echo '$(GENKSYMS):: ;' >> $(dot-target).tmp;              \
+       fi;                                                               \
+       rm -f $(depfile) $(@D)/.tmp_$(@F:.o=.?);                          \
        mv -f $(dot-target).tmp $(dot-target).cmd
 endef
 
index b4ca38a..e063657 100644 (file)
@@ -104,9 +104,11 @@ else
 debug_flags =
 endif
 
-orig_c_flags   = $(KBUILD_CFLAGS) $(ccflags-y) $(CFLAGS_$(basetarget).o)
+orig_c_flags   = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS)                     \
+                 $(ccflags-y) $(CFLAGS_$(basetarget).o)
 _c_flags       = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags))
-_a_flags       = $(KBUILD_AFLAGS) $(asflags-y) $(AFLAGS_$(basetarget).o)
+_a_flags       = $(KBUILD_CPPFLAGS) $(KBUILD_AFLAGS)                     \
+                 $(asflags-y) $(AFLAGS_$(basetarget).o)
 _cpp_flags     = $(KBUILD_CPPFLAGS) $(cppflags-y) $(CPPFLAGS_$(@F))
 
 # If building the kernel in a separate objtree expand all occurrences
@@ -127,15 +129,16 @@ __a_flags =                          $(call flags,_a_flags)
 __cpp_flags     =                          $(call flags,_cpp_flags)
 endif
 
-c_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(KBUILD_CPPFLAGS) \
-                $(__c_flags) $(modkern_cflags) \
+c_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE)     \
+                $(__c_flags) $(modkern_cflags)                           \
                 -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) \
                  $(debug_flags)
 
-a_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(KBUILD_CPPFLAGS) \
+a_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE)     \
                 $(__a_flags) $(modkern_aflags)
 
-cpp_flags      = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(__cpp_flags)
+cpp_flags      = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE)     \
+                $(__cpp_flags)
 
 ld_flags       = $(LDFLAGS) $(ldflags-y)
 
index efa5d94..a5122dc 100644 (file)
@@ -17,7 +17,8 @@ __modinst: $(modules)
        @:
 
 quiet_cmd_modules_install = INSTALL $@
-      cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@)
+      cmd_modules_install = mkdir -p $(2); \
+                           $(mod_strip_cmd) $@ $(2)/$(notdir $@) || cp $@ $(2)
 
 # Modules built outside the kernel source tree go into extra by default
 INSTALL_MOD_DIR ?= extra
index 235d393..4b00647 100755 (executable)
@@ -7,7 +7,7 @@
 # AFLAGS=--32 decodecode < 386.oops
 
 cleanup() {
-       rm -f $T $T.s $T.o
+       rm -f $T $T.s $T.o $T.oo $T.aa  $T.aaa
        exit 1
 }
 
@@ -44,21 +44,33 @@ if [ $marker -eq 0 ]; then
        marker=`expr index "$code" "\("`
 fi
 
+touch $T.oo
 if [ $marker -ne 0 ]; then
-       beforemark=`echo "$code" | cut -c-$((${marker} - 1))`
+       echo All code >> $T.oo
+       echo ======== >> $T.oo
+       beforemark=`echo "$code"`
        echo -n "       .byte 0x" > $T.s
-       echo $beforemark | sed -e 's/ /,0x/g' >> $T.s
-       as $AFLAGS -o $T.o $T.s
-       objdump -S $T.o
-       rm $T.o $T.s
+       echo $beforemark | sed -e 's/ /,0x/g' | sed -e 's/<//g' | sed -e 's/>//g' >> $T.s
+       as $AFLAGS -o $T.o $T.s &> /dev/null
+       objdump -S $T.o | grep -v "/tmp" | grep -v "Disassembly" | grep -v "\.text" | grep -v "^$" &> $T.ooo
+       cat $T.ooo >> $T.oo
+       rm -f $T.o $T.s  $T.ooo
 
 # and fix code at-and-after marker
        code=`echo "$code" | cut -c$((${marker} + 1))-`
 fi
-
+echo Code starting with the faulting instruction  > $T.aa
+echo =========================================== >> $T.aa
 code=`echo $code | sed -e 's/ [<(]/ /;s/[>)] / /;s/ /,0x/g'`
 echo -n "      .byte 0x" > $T.s
 echo $code >> $T.s
-as $AFLAGS -o $T.o $T.s
-objdump -S $T.o
-rm $T $T.s $T.o
+as $AFLAGS -o $T.o $T.s &> /dev/null
+objdump -S $T.o | grep -v "Disassembly" | grep -v "/tmp" | grep -v "\.text" | grep -v "^$" &> $T.aaa
+cat $T.aaa >> $T.aa
+
+faultline=`cat $T.aaa | head -1 | cut -d":" -f2`
+
+cat $T.oo | sed -e "s/\($faultline\)/\*\1     <-- trapping instruction/g"
+echo
+cat $T.aa
+cleanup
index 8187e6f..72997c3 100755 (executable)
@@ -8,8 +8,8 @@ test -e $binoffset || cc -o $binoffset ./scripts/binoffset.c || exit 1
 
 IKCFG_ST="0x49 0x4b 0x43 0x46 0x47 0x5f 0x53 0x54"
 IKCFG_ED="0x49 0x4b 0x43 0x46 0x47 0x5f 0x45 0x44"
-function dump_config {
-    typeset file="$1"
+dump_config() {
+    file="$1"
 
     start=`$binoffset $file $IKCFG_ST 2>/dev/null`
     [ "$?" != "0" ] && start="-1"
@@ -18,8 +18,8 @@ function dump_config {
     fi
     end=`$binoffset $file $IKCFG_ED 2>/dev/null`
 
-    let start="$start + 8"
-    let size="$end - $start"
+    start=`expr $start + 8`
+    size=`expr $end - $start`
 
     dd if="$file" ibs=1 skip="$start" count="$size" 2>/dev/null | zcat
 
index c249274..f8bb4ca 100644 (file)
@@ -42,7 +42,8 @@ static FILE *debugfile;
 int cur_line = 1;
 char *cur_filename;
 
-static int flag_debug, flag_dump_defs, flag_dump_types, flag_warnings;
+static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
+          flag_preserve, flag_warnings, flag_asm;
 static const char *arch = "";
 static const char *mod_prefix = "";
 
@@ -58,6 +59,8 @@ static const char *const symbol_type_name[] = {
 
 static int equal_list(struct string_list *a, struct string_list *b);
 static void print_list(FILE * f, struct string_list *list);
+static void print_location(void);
+static void print_type_name(enum symbol_type type, const char *name);
 
 /*----------------------------------------------------------------------*/
 
@@ -151,27 +154,83 @@ struct symbol *find_symbol(const char *name, enum symbol_type ns)
 
        for (sym = symtab[h]; sym; sym = sym->hash_next)
                if (map_to_ns(sym->type) == map_to_ns(ns) &&
-                   strcmp(name, sym->name) == 0)
+                   strcmp(name, sym->name) == 0 &&
+                   sym->is_declared)
                        break;
 
        return sym;
 }
 
-struct symbol *add_symbol(const char *name, enum symbol_type type,
-                         struct string_list *defn, int is_extern)
+static int is_unknown_symbol(struct symbol *sym)
+{
+       struct string_list *defn;
+
+       return ((sym->type == SYM_STRUCT ||
+                sym->type == SYM_UNION ||
+                sym->type == SYM_ENUM) &&
+               (defn = sym->defn)  && defn->tag == SYM_NORMAL &&
+                       strcmp(defn->string, "}") == 0 &&
+               (defn = defn->next) && defn->tag == SYM_NORMAL &&
+                       strcmp(defn->string, "UNKNOWN") == 0 &&
+               (defn = defn->next) && defn->tag == SYM_NORMAL &&
+                       strcmp(defn->string, "{") == 0);
+}
+
+struct symbol *__add_symbol(const char *name, enum symbol_type type,
+                           struct string_list *defn, int is_extern,
+                           int is_reference)
 {
        unsigned long h = crc32(name) % HASH_BUCKETS;
        struct symbol *sym;
+       enum symbol_status status = STATUS_UNCHANGED;
 
        for (sym = symtab[h]; sym; sym = sym->hash_next) {
-               if (map_to_ns(sym->type) == map_to_ns(type)
-                   && strcmp(name, sym->name) == 0) {
-                       if (!equal_list(sym->defn, defn))
+               if (map_to_ns(sym->type) == map_to_ns(type) &&
+                   strcmp(name, sym->name) == 0) {
+                       if (is_reference)
+                               /* fall through */ ;
+                       else if (sym->type == type &&
+                                equal_list(sym->defn, defn)) {
+                               if (!sym->is_declared && sym->is_override) {
+                                       print_location();
+                                       print_type_name(type, name);
+                                       fprintf(stderr, " modversion is "
+                                               "unchanged\n");
+                               }
+                               sym->is_declared = 1;
+                               return sym;
+                       } else if (!sym->is_declared) {
+                               if (sym->is_override && flag_preserve) {
+                                       print_location();
+                                       fprintf(stderr, "ignoring ");
+                                       print_type_name(type, name);
+                                       fprintf(stderr, " modversion change\n");
+                                       sym->is_declared = 1;
+                                       return sym;
+                               } else {
+                                       status = is_unknown_symbol(sym) ?
+                                               STATUS_DEFINED : STATUS_MODIFIED;
+                               }
+                       } else {
                                error_with_pos("redefinition of %s", name);
-                       return sym;
+                               return sym;
+                       }
+                       break;
                }
        }
 
+       if (sym) {
+               struct symbol **psym;
+
+               for (psym = &symtab[h]; *psym; psym = &(*psym)->hash_next) {
+                       if (*psym == sym) {
+                               *psym = sym->hash_next;
+                               break;
+                       }
+               }
+               --nsyms;
+       }
+
        sym = xmalloc(sizeof(*sym));
        sym->name = name;
        sym->type = type;
@@ -183,6 +242,10 @@ struct symbol *add_symbol(const char *name, enum symbol_type type,
        sym->hash_next = symtab[h];
        symtab[h] = sym;
 
+       sym->is_declared = !is_reference;
+       sym->status = status;
+       sym->is_override = 0;
+
        if (flag_debug) {
                fprintf(debugfile, "Defn for %s %s == <",
                        symbol_type_name[type], name);
@@ -196,6 +259,18 @@ struct symbol *add_symbol(const char *name, enum symbol_type type,
        return sym;
 }
 
+struct symbol *add_symbol(const char *name, enum symbol_type type,
+                         struct string_list *defn, int is_extern)
+{
+       return __add_symbol(name, type, defn, is_extern, 0);
+}
+
+struct symbol *add_reference_symbol(const char *name, enum symbol_type type,
+                                   struct string_list *defn, int is_extern)
+{
+       return __add_symbol(name, type, defn, is_extern, 1);
+}
+
 /*----------------------------------------------------------------------*/
 
 void free_node(struct string_list *node)
@@ -236,6 +311,90 @@ static int equal_list(struct string_list *a, struct string_list *b)
        return !a && !b;
 }
 
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+struct string_list *read_node(FILE *f)
+{
+       char buffer[256];
+       struct string_list node = {
+               .string = buffer,
+               .tag = SYM_NORMAL };
+       int c;
+
+       while ((c = fgetc(f)) != EOF) {
+               if (c == ' ') {
+                       if (node.string == buffer)
+                               continue;
+                       break;
+               } else if (c == '\n') {
+                       if (node.string == buffer)
+                               return NULL;
+                       ungetc(c, f);
+                       break;
+               }
+               if (node.string >= buffer + sizeof(buffer) - 1) {
+                       fprintf(stderr, "Token too long\n");
+                       exit(1);
+               }
+               *node.string++ = c;
+       }
+       if (node.string == buffer)
+               return NULL;
+       *node.string = 0;
+       node.string = buffer;
+
+       if (node.string[1] == '#') {
+               int n;
+
+               for (n = 0; n < ARRAY_SIZE(symbol_type_name); n++) {
+                       if (node.string[0] == symbol_type_name[n][0]) {
+                               node.tag = n;
+                               node.string += 2;
+                               return copy_node(&node);
+                       }
+               }
+               fprintf(stderr, "Unknown type %c\n", node.string[0]);
+               exit(1);
+       }
+       return copy_node(&node);
+}
+
+static void read_reference(FILE *f)
+{
+       while (!feof(f)) {
+               struct string_list *defn = NULL;
+               struct string_list *sym, *def;
+               int is_extern = 0, is_override = 0;
+               struct symbol *subsym;
+
+               sym = read_node(f);
+               if (sym && sym->tag == SYM_NORMAL &&
+                   !strcmp(sym->string, "override")) {
+                       is_override = 1;
+                       free_node(sym);
+                       sym = read_node(f);
+               }
+               if (!sym)
+                       continue;
+               def = read_node(f);
+               if (def && def->tag == SYM_NORMAL &&
+                   !strcmp(def->string, "extern")) {
+                       is_extern = 1;
+                       free_node(def);
+                       def = read_node(f);
+               }
+               while (def) {
+                       def->next = defn;
+                       defn = def;
+                       def = read_node(f);
+               }
+               subsym = add_reference_symbol(xstrdup(sym->string), sym->tag,
+                                             defn, is_extern);
+               subsym->is_override = is_override;
+               free_node(sym);
+       }
+}
+
 static void print_node(FILE * f, struct string_list *list)
 {
        if (list->tag != SYM_NORMAL) {
@@ -311,6 +470,7 @@ static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
 
                case SYM_TYPEDEF:
                        subsym = find_symbol(cur->string, cur->tag);
+                       /* FIXME: Bad reference files can segfault here. */
                        if (subsym->expansion_trail) {
                                if (flag_dump_defs)
                                        fprintf(debugfile, "%s ", cur->string);
@@ -347,9 +507,22 @@ static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
                                t = n;
 
                                n = xmalloc(sizeof(*n));
-                               n->string = xstrdup("{ UNKNOWN }");
+                               n->string = xstrdup("{");
+                               n->tag = SYM_NORMAL;
+                               n->next = t;
+                               t = n;
+
+                               n = xmalloc(sizeof(*n));
+                               n->string = xstrdup("UNKNOWN");
+                               n->tag = SYM_NORMAL;
+                               n->next = t;
+                               t = n;
+
+                               n = xmalloc(sizeof(*n));
+                               n->string = xstrdup("}");
                                n->tag = SYM_NORMAL;
                                n->next = t;
+                               t = n;
 
                                subsym =
                                    add_symbol(cur->string, cur->tag, n, 0);
@@ -397,37 +570,75 @@ void export_symbol(const char *name)
                error_with_pos("export undefined symbol %s", name);
        else {
                unsigned long crc;
+               int has_changed = 0;
 
                if (flag_dump_defs)
                        fprintf(debugfile, "Export %s == <", name);
 
                expansion_trail = (struct symbol *)-1L;
 
+               sym->expansion_trail = expansion_trail;
+               expansion_trail = sym;
                crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff;
 
                sym = expansion_trail;
                while (sym != (struct symbol *)-1L) {
                        struct symbol *n = sym->expansion_trail;
+
+                       if (sym->status != STATUS_UNCHANGED) {
+                               if (!has_changed) {
+                                       print_location();
+                                       fprintf(stderr, "%s: %s: modversion "
+                                               "changed because of changes "
+                                               "in ", flag_preserve ? "error" :
+                                                      "warning", name);
+                               } else
+                                       fprintf(stderr, ", ");
+                               print_type_name(sym->type, sym->name);
+                               if (sym->status == STATUS_DEFINED)
+                                       fprintf(stderr, " (became defined)");
+                               has_changed = 1;
+                               if (flag_preserve)
+                                       errors++;
+                       }
                        sym->expansion_trail = 0;
                        sym = n;
                }
+               if (has_changed)
+                       fprintf(stderr, "\n");
 
                if (flag_dump_defs)
                        fputs(">\n", debugfile);
 
-               /* Used as a linker script. */
-               printf("%s__crc_%s = 0x%08lx ;\n", mod_prefix, name, crc);
+               /* Used as assembly source or a linker script. */
+               printf(flag_asm
+                      ? ".equiv %s__crc_%s, %#08lx\n"
+                      : "%s__crc_%s = %#08lx ;\n",
+                      mod_prefix, name, crc);
        }
 }
 
 /*----------------------------------------------------------------------*/
+
+static void print_location(void)
+{
+       fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line);
+}
+
+static void print_type_name(enum symbol_type type, const char *name)
+{
+       if (type != SYM_NORMAL)
+               fprintf(stderr, "%s %s", symbol_type_name[type], name);
+       else
+               fprintf(stderr, "%s", name);
+}
+
 void error_with_pos(const char *fmt, ...)
 {
        va_list args;
 
        if (flag_warnings) {
-               fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>",
-                       cur_line);
+               print_location();
 
                va_start(args, fmt);
                vfprintf(stderr, fmt, args);
@@ -440,21 +651,27 @@ void error_with_pos(const char *fmt, ...)
 
 static void genksyms_usage(void)
 {
-       fputs("Usage:\n" "genksyms [-adDTwqhV] > /path/to/.tmp_obj.ver\n" "\n"
+       fputs("Usage:\n" "genksyms [-aAdDTwqhV] > /path/to/.tmp_obj.ver\n" "\n"
 #ifdef __GNU_LIBRARY__
              "  -a, --arch            Select architecture\n"
+             "  -A, --asm             Generate assembly rather than linker script\n"
              "  -d, --debug           Increment the debug level (repeatable)\n"
              "  -D, --dump            Dump expanded symbol defs (for debugging only)\n"
-             "  -T, --dump-types file Dump expanded types into file (for debugging only)\n"
+             "  -r, --reference file  Read reference symbols from a file\n"
+             "  -T, --dump-types file Dump expanded types into file\n"
+             "  -p, --preserve        Preserve reference modversions or fail\n"
              "  -w, --warnings        Enable warnings\n"
              "  -q, --quiet           Disable warnings (default)\n"
              "  -h, --help            Print this message\n"
              "  -V, --version         Print the release version\n"
 #else                          /* __GNU_LIBRARY__ */
              "  -a                    Select architecture\n"
+             "  -A                    Generate assembly rather than linker script\n"
              "  -d                    Increment the debug level (repeatable)\n"
              "  -D                    Dump expanded symbol defs (for debugging only)\n"
-             "  -T file               Dump expanded types into file (for debugging only)\n"
+             "  -r file               Read reference symbols from a file\n"
+             "  -T file               Dump expanded types into file\n"
+             "  -p                    Preserve reference modversions or fail\n"
              "  -w                    Enable warnings\n"
              "  -q                    Disable warnings (default)\n"
              "  -h                    Print this message\n"
@@ -465,26 +682,29 @@ static void genksyms_usage(void)
 
 int main(int argc, char **argv)
 {
-       FILE *dumpfile = NULL;
+       FILE *dumpfile = NULL, *ref_file = NULL;
        int o;
 
 #ifdef __GNU_LIBRARY__
        struct option long_opts[] = {
                {"arch", 1, 0, 'a'},
+               {"asm", 0, 0, 'A'},
                {"debug", 0, 0, 'd'},
                {"warnings", 0, 0, 'w'},
                {"quiet", 0, 0, 'q'},
                {"dump", 0, 0, 'D'},
+               {"reference", 1, 0, 'r'},
                {"dump-types", 1, 0, 'T'},
+               {"preserve", 0, 0, 'p'},
                {"version", 0, 0, 'V'},
                {"help", 0, 0, 'h'},
                {0, 0, 0, 0}
        };
 
-       while ((o = getopt_long(argc, argv, "a:dwqVDT:h",
+       while ((o = getopt_long(argc, argv, "a:dwqVADr:T:ph",
                                &long_opts[0], NULL)) != EOF)
 #else                          /* __GNU_LIBRARY__ */
-       while ((o = getopt(argc, argv, "a:dwqVDT:h")) != EOF)
+       while ((o = getopt(argc, argv, "a:dwqVADr:T:ph")) != EOF)
 #endif                         /* __GNU_LIBRARY__ */
                switch (o) {
                case 'a':
@@ -502,9 +722,20 @@ int main(int argc, char **argv)
                case 'V':
                        fputs("genksyms version 2.5.60\n", stderr);
                        break;
+               case 'A':
+                       flag_asm = 1;
+                       break;
                case 'D':
                        flag_dump_defs = 1;
                        break;
+               case 'r':
+                       flag_reference = 1;
+                       ref_file = fopen(optarg, "r");
+                       if (!ref_file) {
+                               perror(optarg);
+                               return 1;
+                       }
+                       break;
                case 'T':
                        flag_dump_types = 1;
                        dumpfile = fopen(optarg, "w");
@@ -513,6 +744,9 @@ int main(int argc, char **argv)
                                return 1;
                        }
                        break;
+               case 'p':
+                       flag_preserve = 1;
+                       break;
                case 'h':
                        genksyms_usage();
                        return 0;
@@ -533,12 +767,17 @@ int main(int argc, char **argv)
                /* setlinebuf(debugfile); */
        }
 
+       if (flag_reference)
+               read_reference(ref_file);
+
        yyparse();
 
        if (flag_dump_types && visited_symbols) {
                while (visited_symbols != (struct symbol *)-1L) {
                        struct symbol *sym = visited_symbols;
 
+                       if (sym->is_override)
+                               fputs("override ", dumpfile);
                        if (sym->type != SYM_NORMAL) {
                                putc(symbol_type_name[sym->type][0], dumpfile);
                                putc('#', dumpfile);
index 2668287..25c4d40 100644 (file)
@@ -29,6 +29,10 @@ enum symbol_type {
        SYM_NORMAL, SYM_TYPEDEF, SYM_ENUM, SYM_STRUCT, SYM_UNION
 };
 
+enum symbol_status {
+       STATUS_UNCHANGED, STATUS_DEFINED, STATUS_MODIFIED
+};
+
 struct string_list {
        struct string_list *next;
        enum symbol_type tag;
@@ -43,6 +47,9 @@ struct symbol {
        struct symbol *expansion_trail;
        struct symbol *visited;
        int is_extern;
+       int is_declared;
+       enum symbol_status status;
+       int is_override;
 };
 
 typedef struct string_list **yystype;
index 971e011..83484fe 100644 (file)
@@ -1,4 +1,4 @@
-/* ANSI-C code produced by gperf version 3.0.2 */
+/* ANSI-C code produced by gperf version 3.0.1 */
 /* Command-line: gperf -L ANSI-C -a -C -E -g -H is_reserved_hash -k '1,3,$' -N is_reserved_word -p -t scripts/genksyms/keywords.gperf  */
 
 #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
@@ -32,7 +32,7 @@
 
 #line 3 "scripts/genksyms/keywords.gperf"
 struct resword { const char *name; int token; };
-/* maximum key range = 62, duplicates = 0 */
+/* maximum key range = 64, duplicates = 0 */
 
 #ifdef __GNUC__
 __inline
@@ -46,32 +46,32 @@ is_reserved_hash (register const char *str, register unsigned int len)
 {
   static const unsigned char asso_values[] =
     {
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65,  5,
-      65, 65, 65, 65, 65, 65, 35, 65, 65, 65,
-       0, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65,  0, 65,  0, 65,  5,
-      20, 15, 10, 30, 65, 15, 65, 65, 20,  0,
-      10, 35, 20, 65, 10,  5,  0, 10,  5, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67,  0,
+      67, 67, 67, 67, 67, 67, 15, 67, 67, 67,
+       0, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67,  0, 67,  0, 67,  5,
+      25, 20, 15, 30, 67, 15, 67, 67, 10,  0,
+      10, 40, 20, 67, 10,  5,  0, 10, 15, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67
     };
   return len + asso_values[(unsigned char)str[2]] + asso_values[(unsigned char)str[0]] + asso_values[(unsigned char)str[len - 1]];
 }
@@ -84,116 +84,119 @@ is_reserved_word (register const char *str, register unsigned int len)
 {
   enum
     {
-      TOTAL_KEYWORDS = 43,
+      TOTAL_KEYWORDS = 45,
       MIN_WORD_LENGTH = 3,
       MAX_WORD_LENGTH = 24,
       MIN_HASH_VALUE = 3,
-      MAX_HASH_VALUE = 64
+      MAX_HASH_VALUE = 66
     };
 
   static const struct resword wordlist[] =
     {
       {""}, {""}, {""},
-#line 26 "scripts/genksyms/keywords.gperf"
+#line 28 "scripts/genksyms/keywords.gperf"
       {"asm", ASM_KEYW},
       {""},
-#line 8 "scripts/genksyms/keywords.gperf"
+#line 10 "scripts/genksyms/keywords.gperf"
       {"__asm", ASM_KEYW},
       {""},
-#line 9 "scripts/genksyms/keywords.gperf"
+#line 11 "scripts/genksyms/keywords.gperf"
       {"__asm__", ASM_KEYW},
       {""}, {""},
-#line 52 "scripts/genksyms/keywords.gperf"
+#line 54 "scripts/genksyms/keywords.gperf"
       {"__typeof__", TYPEOF_KEYW},
       {""},
-#line 12 "scripts/genksyms/keywords.gperf"
+#line 14 "scripts/genksyms/keywords.gperf"
       {"__const", CONST_KEYW},
-#line 11 "scripts/genksyms/keywords.gperf"
-      {"__attribute__", ATTRIBUTE_KEYW},
 #line 13 "scripts/genksyms/keywords.gperf"
+      {"__attribute__", ATTRIBUTE_KEYW},
+#line 15 "scripts/genksyms/keywords.gperf"
       {"__const__", CONST_KEYW},
-#line 18 "scripts/genksyms/keywords.gperf"
+#line 20 "scripts/genksyms/keywords.gperf"
       {"__signed__", SIGNED_KEYW},
-#line 44 "scripts/genksyms/keywords.gperf"
+#line 46 "scripts/genksyms/keywords.gperf"
       {"static", STATIC_KEYW},
-#line 20 "scripts/genksyms/keywords.gperf"
-      {"__volatile__", VOLATILE_KEYW},
-#line 39 "scripts/genksyms/keywords.gperf"
+      {""},
+#line 41 "scripts/genksyms/keywords.gperf"
       {"int", INT_KEYW},
-#line 32 "scripts/genksyms/keywords.gperf"
+#line 34 "scripts/genksyms/keywords.gperf"
       {"char", CHAR_KEYW},
-#line 33 "scripts/genksyms/keywords.gperf"
+#line 35 "scripts/genksyms/keywords.gperf"
       {"const", CONST_KEYW},
-#line 45 "scripts/genksyms/keywords.gperf"
+#line 47 "scripts/genksyms/keywords.gperf"
       {"struct", STRUCT_KEYW},
-#line 24 "scripts/genksyms/keywords.gperf"
+#line 26 "scripts/genksyms/keywords.gperf"
       {"__restrict__", RESTRICT_KEYW},
-#line 25 "scripts/genksyms/keywords.gperf"
+#line 27 "scripts/genksyms/keywords.gperf"
       {"restrict", RESTRICT_KEYW},
-#line 23 "scripts/genksyms/keywords.gperf"
-      {"_restrict", RESTRICT_KEYW},
-#line 16 "scripts/genksyms/keywords.gperf"
+#line 7 "scripts/genksyms/keywords.gperf"
+      {"EXPORT_SYMBOL_GPL_FUTURE", EXPORT_SYMBOL_KEYW},
+#line 18 "scripts/genksyms/keywords.gperf"
       {"__inline__", INLINE_KEYW},
-#line 10 "scripts/genksyms/keywords.gperf"
-      {"__attribute", ATTRIBUTE_KEYW},
       {""},
-#line 14 "scripts/genksyms/keywords.gperf"
+#line 22 "scripts/genksyms/keywords.gperf"
+      {"__volatile__", VOLATILE_KEYW},
+#line 5 "scripts/genksyms/keywords.gperf"
+      {"EXPORT_SYMBOL", EXPORT_SYMBOL_KEYW},
+#line 25 "scripts/genksyms/keywords.gperf"
+      {"_restrict", RESTRICT_KEYW},
+      {""},
+#line 12 "scripts/genksyms/keywords.gperf"
+      {"__attribute", ATTRIBUTE_KEYW},
+#line 6 "scripts/genksyms/keywords.gperf"
+      {"EXPORT_SYMBOL_GPL", EXPORT_SYMBOL_KEYW},
+#line 16 "scripts/genksyms/keywords.gperf"
       {"__extension__", EXTENSION_KEYW},
-#line 35 "scripts/genksyms/keywords.gperf"
+#line 37 "scripts/genksyms/keywords.gperf"
       {"enum", ENUM_KEYW},
-#line 19 "scripts/genksyms/keywords.gperf"
-      {"__volatile", VOLATILE_KEYW},
-#line 36 "scripts/genksyms/keywords.gperf"
+#line 8 "scripts/genksyms/keywords.gperf"
+      {"EXPORT_UNUSED_SYMBOL", EXPORT_SYMBOL_KEYW},
+#line 38 "scripts/genksyms/keywords.gperf"
       {"extern", EXTERN_KEYW},
       {""},
-#line 17 "scripts/genksyms/keywords.gperf"
+#line 19 "scripts/genksyms/keywords.gperf"
       {"__signed", SIGNED_KEYW},
-#line 7 "scripts/genksyms/keywords.gperf"
-      {"EXPORT_SYMBOL_GPL_FUTURE", EXPORT_SYMBOL_KEYW},
-      {""},
-#line 51 "scripts/genksyms/keywords.gperf"
+#line 9 "scripts/genksyms/keywords.gperf"
+      {"EXPORT_UNUSED_SYMBOL_GPL", EXPORT_SYMBOL_KEYW},
+#line 49 "scripts/genksyms/keywords.gperf"
+      {"union", UNION_KEYW},
+#line 53 "scripts/genksyms/keywords.gperf"
       {"typeof", TYPEOF_KEYW},
-#line 46 "scripts/genksyms/keywords.gperf"
+#line 48 "scripts/genksyms/keywords.gperf"
       {"typedef", TYPEDEF_KEYW},
-#line 15 "scripts/genksyms/keywords.gperf"
+#line 17 "scripts/genksyms/keywords.gperf"
       {"__inline", INLINE_KEYW},
-#line 31 "scripts/genksyms/keywords.gperf"
+#line 33 "scripts/genksyms/keywords.gperf"
       {"auto", AUTO_KEYW},
-#line 47 "scripts/genksyms/keywords.gperf"
-      {"union", UNION_KEYW},
-      {""}, {""},
-#line 48 "scripts/genksyms/keywords.gperf"
-      {"unsigned", UNSIGNED_KEYW},
-#line 49 "scripts/genksyms/keywords.gperf"
-      {"void", VOID_KEYW},
-#line 42 "scripts/genksyms/keywords.gperf"
-      {"short", SHORT_KEYW},
+#line 21 "scripts/genksyms/keywords.gperf"
+      {"__volatile", VOLATILE_KEYW},
       {""}, {""},
 #line 50 "scripts/genksyms/keywords.gperf"
-      {"volatile", VOLATILE_KEYW},
-      {""},
-#line 37 "scripts/genksyms/keywords.gperf"
-      {"float", FLOAT_KEYW},
-#line 34 "scripts/genksyms/keywords.gperf"
-      {"double", DOUBLE_KEYW},
+      {"unsigned", UNSIGNED_KEYW},
       {""},
-#line 5 "scripts/genksyms/keywords.gperf"
-      {"EXPORT_SYMBOL", EXPORT_SYMBOL_KEYW},
-      {""}, {""},
-#line 38 "scripts/genksyms/keywords.gperf"
+#line 44 "scripts/genksyms/keywords.gperf"
+      {"short", SHORT_KEYW},
+#line 40 "scripts/genksyms/keywords.gperf"
       {"inline", INLINE_KEYW},
-#line 6 "scripts/genksyms/keywords.gperf"
-      {"EXPORT_SYMBOL_GPL", EXPORT_SYMBOL_KEYW},
-#line 41 "scripts/genksyms/keywords.gperf"
-      {"register", REGISTER_KEYW},
       {""},
-#line 22 "scripts/genksyms/keywords.gperf"
+#line 52 "scripts/genksyms/keywords.gperf"
+      {"volatile", VOLATILE_KEYW},
+#line 42 "scripts/genksyms/keywords.gperf"
+      {"long", LONG_KEYW},
+#line 24 "scripts/genksyms/keywords.gperf"
       {"_Bool", BOOL_KEYW},
-#line 43 "scripts/genksyms/keywords.gperf"
-      {"signed", SIGNED_KEYW},
       {""}, {""},
-#line 40 "scripts/genksyms/keywords.gperf"
-      {"long", LONG_KEYW}
+#line 43 "scripts/genksyms/keywords.gperf"
+      {"register", REGISTER_KEYW},
+#line 51 "scripts/genksyms/keywords.gperf"
+      {"void", VOID_KEYW},
+#line 39 "scripts/genksyms/keywords.gperf"
+      {"float", FLOAT_KEYW},
+#line 36 "scripts/genksyms/keywords.gperf"
+      {"double", DOUBLE_KEYW},
+      {""}, {""}, {""}, {""},
+#line 45 "scripts/genksyms/keywords.gperf"
+      {"signed", SIGNED_KEYW}
     };
 
   if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
index 5ef3733..8abe7ab 100644 (file)
@@ -5,6 +5,8 @@ struct resword { const char *name; int token; }
 EXPORT_SYMBOL, EXPORT_SYMBOL_KEYW
 EXPORT_SYMBOL_GPL, EXPORT_SYMBOL_KEYW
 EXPORT_SYMBOL_GPL_FUTURE, EXPORT_SYMBOL_KEYW
+EXPORT_UNUSED_SYMBOL, EXPORT_SYMBOL_KEYW
+EXPORT_UNUSED_SYMBOL_GPL, EXPORT_SYMBOL_KEYW
 __asm, ASM_KEYW
 __asm__, ASM_KEYW
 __attribute, ATTRIBUTE_KEYW
diff --git a/scripts/headerdep.pl b/scripts/headerdep.pl
new file mode 100755 (executable)
index 0000000..97399da
--- /dev/null
@@ -0,0 +1,193 @@
+#! /usr/bin/perl
+#
+# Detect cycles in the header file dependency graph
+# Vegard Nossum <vegardno@ifi.uio.no>
+#
+
+use strict;
+use warnings;
+
+use Getopt::Long;
+
+my $opt_all;
+my @opt_include;
+my $opt_graph;
+
+&Getopt::Long::Configure(qw(bundling pass_through));
+&GetOptions(
+       help    => \&help,
+       version => \&version,
+
+       all     => \$opt_all,
+       I       => \@opt_include,
+       graph   => \$opt_graph,
+);
+
+push @opt_include, 'include';
+my %deps = ();
+my %linenos = ();
+
+my @headers = grep { strip($_) } @ARGV;
+
+parse_all(@headers);
+
+if($opt_graph) {
+       graph();
+} else {
+       detect_cycles(@headers);
+}
+
+
+sub help {
+       print "Usage: $0 [options] file...\n";
+       print "\n";
+       print "Options:\n";
+       print "  --all\n";
+       print "  --graph\n";
+       print "\n";
+       print "  -I includedir\n";
+       print "\n";
+       print "To make nice graphs, try:\n";
+       print "  $0 --graph include/linux/kernel.h | dot -Tpng -o graph.png\n";
+       exit;
+}
+
+sub version {
+       print "headerdep version 2\n";
+       exit;
+}
+
+# Get a file name that is relative to our include paths
+sub strip {
+       my $filename = shift;
+
+       for my $i (@opt_include) {
+               my $stripped = $filename;
+               $stripped =~ s/^$i\///;
+
+               return $stripped if $stripped ne $filename;
+       }
+
+       return $filename;
+}
+
+# Search for the file name in the list of include paths
+sub search {
+       my $filename = shift;
+       return $filename if -f $filename;
+
+       for my $i (@opt_include) {
+               my $path = "$i/$filename";
+               return $path if -f $path;
+       }
+
+       return undef;
+}
+
+sub parse_all {
+       # Parse all the headers.
+       my @queue = @_;
+       while(@queue) {
+               my $header = pop @queue;
+               next if exists $deps{$header};
+
+               $deps{$header} = [] unless exists $deps{$header};
+
+               my $path = search($header);
+               next unless $path;
+
+               open(my $file, '<', $path) or die($!);
+               chomp(my @lines = <$file>);
+               close($file);
+
+               for my $i (0 .. $#lines) {
+                       my $line = $lines[$i];
+                       if(my($dep) = ($line =~ m/^#\s*include\s*<(.*?)>/)) {
+                               push @queue, $dep;
+                               push @{$deps{$header}}, [$i + 1, $dep];
+                       }
+               }
+       }
+}
+
+sub print_cycle {
+       # $cycle[n] includes $cycle[n + 1];
+       # $cycle[-1] will be the culprit
+       my $cycle = shift;
+
+       # Adjust the line numbers
+       for my $i (0 .. $#$cycle - 1) {
+               $cycle->[$i]->[0] = $cycle->[$i + 1]->[0];
+       }
+       $cycle->[-1]->[0] = 0;
+
+       my $first = shift @$cycle;
+       my $last = pop @$cycle;
+
+       my $msg = "In file included";
+       printf "%s from %s,\n", $msg, $last->[1] if defined $last;
+
+       for my $header (reverse @$cycle) {
+               printf "%s from %s:%d%s\n",
+                       " " x length $msg,
+                       $header->[1], $header->[0],
+                       $header->[1] eq $last->[1] ? ' <-- here' : '';
+       }
+
+       printf "%s:%d: warning: recursive header inclusion\n",
+               $first->[1], $first->[0];
+}
+
+# Find and print the smallest cycle starting in the specified node.
+sub detect_cycles {
+       my @queue = map { [[0, $_]] } @_;
+       while(@queue) {
+               my $top = pop @queue;
+               my $name = $top->[-1]->[1];
+
+               for my $dep (@{$deps{$name}}) {
+                       my $chain = [@$top, [$dep->[0], $dep->[1]]];
+
+                       # If the dep already exists in the chain, we have a
+                       # cycle...
+                       if(grep { $_->[1] eq $dep->[1] } @$top) {
+                               print_cycle($chain);
+                               next if $opt_all;
+                               return;
+                       }
+
+                       push @queue, $chain;
+               }
+       }
+}
+
+sub mangle {
+       $_ = shift;
+       s/\//__/g;
+       s/\./_/g;
+       s/-/_/g;
+       $_;
+}
+
+# Output dependency graph in GraphViz language.
+sub graph {
+       print "digraph {\n";
+
+       print "\t/* vertices */\n";
+       for my $header (keys %deps) {
+               printf "\t%s [label=\"%s\"];\n",
+                       mangle($header), $header;
+       }
+
+       print "\n";
+
+       print "\t/* edges */\n";
+       for my $header (keys %deps) {
+               for my $dep (@{$deps{$header}}) {
+                       printf "\t%s -> %s;\n",
+                               mangle($header), mangle($dep->[1]);
+               }
+       }
+
+       print "}\n";
+}
index ad2434b..9275812 100644 (file)
@@ -130,18 +130,9 @@ static int read_symbol(FILE *in, struct sym_entry *s)
 static int symbol_valid(struct sym_entry *s)
 {
        /* Symbols which vary between passes.  Passes 1 and 2 must have
-        * identical symbol lists.  The kallsyms_* symbols below are only added
-        * after pass 1, they would be included in pass 2 when --all-symbols is
-        * specified so exclude them to get a stable symbol list.
+        * identical symbol lists.
         */
        static char *special_symbols[] = {
-               "kallsyms_addresses",
-               "kallsyms_num_syms",
-               "kallsyms_names",
-               "kallsyms_markers",
-               "kallsyms_token_table",
-               "kallsyms_token_index",
-
        /* Exclude linker generated symbols which vary between passes */
                "_SDA_BASE_",           /* ppc */
                "_SDA2_BASE_",          /* ppc */
@@ -173,7 +164,9 @@ static int symbol_valid(struct sym_entry *s)
        }
 
        /* Exclude symbols which vary between passes. */
-       if (strstr((char *)s->sym + offset, "_compiled."))
+       if (strstr((char *)s->sym + offset, "_compiled.") ||
+           strncmp((char*)s->sym + offset, "__compound_literal.", 19) == 0 ||
+           strncmp((char*)s->sym + offset, "__compound_literal$", 19) == 0)
                return 0;
 
        for (i = 0; special_symbols[i]; i++)
@@ -550,8 +543,10 @@ int main(int argc, char **argv)
                usage();
 
        read_map(stdin);
-       sort_symbols();
-       optimize_token_table();
+       if (table_cnt) {
+               sort_symbols();
+               optimize_token_table();
+       }
        write_src();
 
        return 0;
index 5552154..fcef0f5 100644 (file)
@@ -52,7 +52,7 @@ EOF
 }
 
 usage() {
-       printf "Usage: $0 [-check compiler options|-header|-library]\n"
+       printf "Usage: $0 [-check compiler options|-ccflags|-ldflags compiler options]\n"
 }
 
 if [ $# -eq 0 ]; then
index d27aad7..8bb83a1 100755 (executable)
@@ -289,6 +289,8 @@ my %parameterdescs;
 my @parameterlist;
 my %sections;
 my @sectionlist;
+my $sectcheck;
+my $struct_actual;
 
 my $contents = "";
 my $section_default = "Description";   # default section
@@ -378,10 +380,12 @@ sub dump_section {
 #      print STDERR "parameter def '$1' = '$contents'\n";
        $name = $1;
        $parameterdescs{$name} = $contents;
+       $sectcheck = $sectcheck . $name . " ";
     } elsif ($name eq "@\.\.\.") {
 #      print STDERR "parameter def '...' = '$contents'\n";
        $name = "...";
        $parameterdescs{$name} = $contents;
+       $sectcheck = $sectcheck . $name . " ";
     } else {
 #      print STDERR "other section '$name' = '$contents'\n";
        if (defined($sections{$name}) && ($sections{$name} ne "")) {
@@ -1405,21 +1409,25 @@ sub dump_union($$) {
 sub dump_struct($$) {
     my $x = shift;
     my $file = shift;
+    my $nested;
 
     if ($x =~/(struct|union)\s+(\w+)\s*{(.*)}/) {
        $declaration_name = $2;
        my $members = $3;
 
        # ignore embedded structs or unions
-       $members =~ s/{.*}//g;
+       $members =~ s/({.*})//g;
+       $nested = $1;
 
        # ignore members marked private:
        $members =~ s/\/\*.*?private:.*?public:.*?\*\///gos;
        $members =~ s/\/\*.*?private:.*//gos;
        # strip comments:
        $members =~ s/\/\*.*?\*\///gos;
+       $nested =~ s/\/\*.*?\*\///gos;
 
        create_parameterlist($members, ';', $file);
+       check_sections($file, $declaration_name, "struct", $sectcheck, $struct_actual, $nested);
 
        output_declaration($declaration_name,
                           'struct',
@@ -1505,6 +1513,14 @@ sub dump_typedef($$) {
     }
 }
 
+sub save_struct_actual($) {
+    my $actual = shift;
+
+    # strip all spaces from the actual param so that it looks like one string item
+    $actual =~ s/\s*//g;
+    $struct_actual = $struct_actual . $actual . " ";
+}
+
 sub create_parameterlist($$$) {
     my $args = shift;
     my $splitter = shift;
@@ -1537,6 +1553,7 @@ sub create_parameterlist($$$) {
            $param = $1;
            $type = $arg;
            $type =~ s/([^\(]+\(\*?)\s*$param/$1/;
+           save_struct_actual($param);
            push_parameter($param, $type, $file);
        } elsif ($arg) {
            $arg =~ s/\s*:\s*/:/g;
@@ -1561,14 +1578,17 @@ sub create_parameterlist($$$) {
 
            foreach $param (@args) {
                if ($param =~ m/^(\*+)\s*(.*)/) {
+                   save_struct_actual($2);
                    push_parameter($2, "$type $1", $file);
                }
                elsif ($param =~ m/(.*?):(\d+)/) {
                    if ($type ne "") { # skip unnamed bit-fields
+                       save_struct_actual($1);
                        push_parameter($1, "$type:$2", $file)
                    }
                }
                else {
+                   save_struct_actual($param);
                    push_parameter($param, $type, $file);
                }
            }
@@ -1634,6 +1654,46 @@ sub push_parameter($$$) {
        $parametertypes{$param} = $type;
 }
 
+sub check_sections($$$$$$) {
+       my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck, $nested) = @_;
+       my @sects = split ' ', $sectcheck;
+       my @prms = split ' ', $prmscheck;
+       my $err;
+       my ($px, $sx);
+       my $prm_clean;          # strip trailing "[array size]" and/or beginning "*"
+
+       foreach $sx (0 .. $#sects) {
+               $err = 1;
+               foreach $px (0 .. $#prms) {
+                       $prm_clean = $prms[$px];
+                       $prm_clean =~ s/\[.*\]//;
+                       $prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//;
+                       ##$prm_clean =~ s/^\**//;
+                       if ($prm_clean eq $sects[$sx]) {
+                               $err = 0;
+                               last;
+                       }
+               }
+               if ($err) {
+                       if ($decl_type eq "function") {
+                               print STDERR "Warning(${file}:$.): " .
+                                       "Excess function parameter " .
+                                       "'$sects[$sx]' " .
+                                       "description in '$decl_name'\n";
+                               ++$warnings;
+                       } else {
+                               if ($nested !~ m/\Q$sects[$sx]\E/) {
+                                   print STDERR "Warning(${file}:$.): " .
+                                       "Excess struct/union/enum/typedef member " .
+                                       "'$sects[$sx]' " .
+                                       "description in '$decl_name'\n";
+                                   ++$warnings;
+                               }
+                       }
+               }
+       }
+}
+
 ##
 # takes a function prototype and the name of the current file being
 # processed and spits out all the details stored in the global
@@ -1699,6 +1759,9 @@ sub dump_function($$) {
        return;
     }
 
+       my $prms = join " ", @parameterlist;
+       check_sections($file, $declaration_name, "function", $sectcheck, $prms, "");
+
     output_declaration($declaration_name,
                       'function',
                       {'function' => $declaration_name,
@@ -1757,6 +1820,8 @@ sub reset_state {
     @parameterlist = ();
     %sections = ();
     @sectionlist = ();
+    $sectcheck = "";
+    $struct_actual = "";
     $prototype = "";
 
     $state = 0;
index a8740df..6a12dd9 100755 (executable)
@@ -4,6 +4,8 @@ SMP=$3
 PREEMPT=$4
 CC=$5
 
+vecho() { [ "${quiet}" = "silent_" ] || echo "$@" ; }
+
 # If compile.h exists already and we don't own autoconf.h
 # (i.e. we're not the same user who did make *config), don't
 # modify compile.h
@@ -11,7 +13,7 @@ CC=$5
 # do "compiled by root"
 
 if [ -r $TARGET -a ! -O include/linux/autoconf.h ]; then
-  echo "  SKIPPED $TARGET"
+  vecho "  SKIPPED $TARGET"
   exit 0
 fi
 
@@ -89,7 +91,7 @@ if [ -r $TARGET ] && \
       cmp -s .tmpver.1 .tmpver.2; then
    rm -f .tmpcompile
 else
-   echo "  UPD     $TARGET"
+   vecho "  UPD     $TARGET"
    mv -f .tmpcompile $TARGET
 fi
 rm -f .tmpver.1 .tmpver.2
index e65d8b3..67d59c7 100644 (file)
@@ -17,7 +17,9 @@ if test -e $2/Makefile && ! grep -q Automatically $2/Makefile
 then
        exit 0
 fi
-echo "  GEN     $2/Makefile"
+if [ "${quiet}" != "silent_" ]; then
+       echo "  GEN     $2/Makefile"
+fi
 
 cat << EOF > $2/Makefile
 # Automatically generated by $0: don't edit
index 6e133a0..1db316a 100644 (file)
@@ -37,9 +37,6 @@
 
 # readprofile starts reading symbols when _stext is found, and
 # continue until it finds a symbol which is not either of 'T', 't',
-# 'W' or 'w'. __crc_ are 'A' and placed in the middle
-# so we just ignore them to let readprofile continue to work.
-# (At least sparc64 has __crc_ in the middle).
-
-$NM -n $1 | grep -v '\( [aNUw] \)\|\(__crc_\)\|\( \$[adt]\)' > $2
+# 'W' or 'w'.
 
+$NM -n $1 | grep -v '\( [aNUw] \)\|\( \$[adt]\)' > $2
index 5e32607..8c6b7b0 100644 (file)
@@ -1,10 +1,6 @@
 # Makefile for the different targets used to generate full packages of a kernel
 # It uses the generic clean infrastructure of kbuild
 
-# Ignore the following files/directories during tar operation
-TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS
-
-
 # RPM target
 # ---------------------------------------------------------------------------
 # The rpm target generates two rpm files:
@@ -47,7 +43,7 @@ rpm-pkg rpm: $(objtree)/kernel.spec FORCE
        set -e; \
        mv -f $(objtree)/.tmp_version $(objtree)/.version
 
-       $(RPM) --target $(UTS_MACHINE) -ta ../$(KERNELPATH).tar.gz
+       $(RPM) $(RPMOPTS) --target $(UTS_MACHINE) -ta ../$(KERNELPATH).tar.gz
        rm ../$(KERNELPATH).tar.gz
 
 clean-files := $(objtree)/kernel.spec
@@ -64,7 +60,8 @@ binrpm-pkg: $(objtree)/binkernel.spec FORCE
        set -e; \
        mv -f $(objtree)/.tmp_version $(objtree)/.version
 
-       $(RPM) --define "_builddir $(srctree)" --target $(UTS_MACHINE) -bb $<
+       $(RPM) $(RPMOPTS) --define "_builddir $(srctree)" --target \
+               $(UTS_MACHINE) -bb $<
 
 clean-files += $(objtree)/binkernel.spec
 
index 72d2335..f6946cf 100755 (executable)
@@ -19,6 +19,11 @@ if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
                fi
        fi
 
+       # Is this git on svn?
+       if git config --get svn-remote.svn.url >/dev/null; then
+               printf -- '-svn%s' "`git-svn find-rev $head`"
+       fi
+
        # Are there uncommitted changes?
        git update-index --refresh --unmerged > /dev/null
        if git diff-index --name-only HEAD | grep -v "^scripts/package" \
@@ -51,7 +56,7 @@ if hgid=`hg id 2>/dev/null`; then
 fi
 
 # Check for svn and a svn repo.
-if rev=`svn info 2>/dev/null | grep '^Revision'`; then
+if rev=`svn info 2>/dev/null | grep '^Last Changed Rev'`; then
        rev=`echo $rev | awk '{print $NF}'`
        changes=`svn status 2>/dev/null | grep '^[AMD]' | wc -l`
 
diff --git a/scripts/strip-symbols b/scripts/strip-symbols
new file mode 100644 (file)
index 0000000..29ee8c1
--- /dev/null
@@ -0,0 +1,22 @@
+<*>
+*.h
+__compound_literal[$.][0-9]*
+__crc_[a-zA-Z_]*
+__exitcall_[a-zA-Z_]*
+__func__[$.][0-9]*
+__FUNCTION__[$.][0-9]*
+gcc[0-9]_compiled[$.]
+__initcall_[a-zA-Z_]*
+__kcrctab_[a-zA-Z_]*
+__kstrtab_[a-zA-Z_]*
+__ksymtab_[a-zA-Z_]*
+__mod_[a-zA-Z_]*[0-9]
+__module_depends
+__param_[a-zA-Z_]*
+__pci_fixup_*PCI_ANY_IDPCI_ANY_ID*
+__pci_fixup_*PCI_ANY_IDPCI_DEVICE_ID_*
+__pci_fixup_*PCI_VENDOR_ID_*PCI_ANY_ID*
+__pci_fixup_*PCI_VENDOR_ID_*PCI_DEVICE_ID_*
+__PRETTY_FUNCTION__[$.][0-9]*
+__setup_[a-zA-Z_]*
+____versions
diff --git a/scripts/tags.sh b/scripts/tags.sh
new file mode 100755 (executable)
index 0000000..4e75472
--- /dev/null
@@ -0,0 +1,160 @@
+#!/bin/sh
+# Generate tags or cscope files
+# Usage tags.sh <mode>
+#
+# mode may be any of: tags, TAGS, cscope
+#
+# Uses the following environment variables:
+# ARCH, SUBARCH, srctree, src, obj
+
+if [ "$KBUILD_VERBOSE" = "1" ]; then
+       set -x
+fi
+
+# This is a duplicate of RCS_FIND_IGNORE without escaped '()'
+ignore="( -name SCCS -o -name BitKeeper -o -name .svn -o \
+          -name CVS  -o -name .pc       -o -name .hg  -o \
+          -name .git )                                   \
+          -prune -o"
+
+# Do not use full path is we do not use O=.. builds
+if [ "${KBUILD_SRC}" = "" ]; then
+       tree=
+else
+       tree=${srctree}/
+fi
+
+# find sources in arch/$ARCH
+find_arch_sources()
+{
+       find ${tree}arch/$1 $ignore -name "$2" -print;
+}
+
+# find sources in arch/$1/include
+find_arch_include_sources()
+{
+       find ${tree}arch/$1/include $ignore -name "$2" -print;
+}
+
+# find sources in include/
+find_include_sources()
+{
+       find ${tree}include $ignore -name config -prune -o -name "$1" -print;
+}
+
+# find sources in rest of tree
+# we could benefit from a list of dirs to search in here
+find_other_sources()
+{
+       find ${tree}* $ignore \
+            \( -name include -o -name arch -o -name '.tmp_*' \) -prune -o \
+              -name "$1" -print;
+}
+
+find_sources()
+{
+       find_arch_sources $1 "$2"
+       find_include_sources "$2"
+       find_other_sources "$2"
+}
+
+all_sources()
+{
+       find_sources $SRCARCH '*.[chS]'
+       if [ ! -z "$archinclude" ]; then
+               find_arch_include_sources $archinclude '*.[chS]'
+       fi
+}
+
+all_kconfigs()
+{
+       find_sources $SRCARCH 'Kconfig*'
+}
+
+all_defconfigs()
+{
+       find_sources $SRCARCH "defconfig"
+}
+
+docscope()
+{
+       (echo \-k; echo \-q; all_sources) > cscope.files
+       cscope -b -f cscope.out
+}
+
+exuberant()
+{
+       all_sources > all
+       all_sources | xargs $1 -a                               \
+       -I __initdata,__exitdata,__acquires,__releases          \
+       -I __read_mostly,____cacheline_aligned                  \
+       -I ____cacheline_aligned_in_smp                         \
+       -I ____cacheline_internodealigned_in_smp                \
+       -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL                      \
+       --extra=+f --c-kinds=+px                                \
+       --regex-asm='/^ENTRY\(([^)]*)\).*/\1/'
+
+       all_kconfigs | xargs $1 -a                              \
+       --langdef=kconfig --language-force=kconfig              \
+       --regex-kconfig='/^[[:blank:]]*(menu|)config[[:blank:]]+([[:alnum:]_]+)/\2/'
+
+       all_kconfigs | xargs $1 -a                              \
+       --langdef=kconfig --language-force=kconfig              \
+       --regex-kconfig='/^[[:blank:]]*(menu|)config[[:blank:]]+([[:alnum:]_]+)/CONFIG_\2/'
+
+       all_defconfigs | xargs -r $1 -a                         \
+       --langdef=dotconfig --language-force=dotconfig          \
+       --regex-dotconfig='/^#?[[:blank:]]*(CONFIG_[[:alnum:]_]+)/\1/'
+
+}
+
+emacs()
+{
+       all_sources | xargs $1 -a
+
+       all_kconfigs | xargs $1 -a                              \
+       --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/'
+
+       all_kconfigs | xargs $1 -a                              \
+       --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/CONFIG_\3/'
+
+       all_defconfigs | xargs -r $1 -a                         \
+       --regex='/^#?[ \t]?\(CONFIG_[a-zA-Z0-9_]+\)/\1/'
+}
+
+xtags()
+{
+       if $1 --version 2>&1 | grep -iq exuberant; then
+               exuberant $1
+       elif $1 --version 2>&1 | grep -iq emacs; then
+               emacs $1
+       else
+               all_sources | xargs $1 -a
+        fi
+}
+
+
+# Support um (which uses SUBARCH)
+if [ "${ARCH}" = "um" ]; then
+       if [ "$SUBARCH" = "i386" ]; then
+               archinclude=x86
+       elif [ "$SUBARCH" = "x86_64" ]; then
+               archinclude=x86
+       else
+               archinclude=${SUBARCH}
+       fi
+fi
+
+case "$1" in
+       "cscope")
+               docscope
+               ;;
+
+       "tags")
+               xtags ctags
+               ;;
+
+       "TAGS")
+               xtags etags
+               ;;
+esac
index 7abc07f..f1d3fe3 100644 (file)
@@ -370,6 +370,30 @@ error:
        return rc;
 }
 
+static char *cpio_replace_env(char *new_location)
+{
+       char expanded[PATH_MAX + 1];
+       char env_var[PATH_MAX + 1];
+       char *start;
+       char *end;
+
+       for (start = NULL; (start = strstr(new_location, "${")); ) {
+               end = strchr(start, '}');
+               if (start < end) {
+                       *env_var = *expanded = '\0';
+                       strncat(env_var, start + 2, end - start - 2);
+                       strncat(expanded, new_location, start - new_location);
+                       strncat(expanded, getenv(env_var), PATH_MAX);
+                       strncat(expanded, end + 1, PATH_MAX);
+                       strncpy(new_location, expanded, PATH_MAX);
+               } else
+                       break;
+       }
+
+       return new_location;
+}
+
+
 static int cpio_mkfile_line(const char *line)
 {
        char name[PATH_MAX + 1];
@@ -415,7 +439,8 @@ static int cpio_mkfile_line(const char *line)
        } else {
                dname = name;
        }
-       rc = cpio_mkfile(dname, location, mode, uid, gid, nlinks);
+       rc = cpio_mkfile(dname, cpio_replace_env(location),
+                        mode, uid, gid, nlinks);
  fail:
        if (dname_len) free(dname);
        return rc;
@@ -439,6 +464,7 @@ void usage(const char *prog)
                "\n"
                "<name>       name of the file/dir/nod/etc in the archive\n"
                "<location>   location of the file in the current filesystem\n"
+               "             expands shell variables quoted with ${}\n"
                "<target>     link target\n"
                "<mode>       mode/permissions of the file\n"
                "<uid>        user id (0=root)\n"