genksyms: track symbol checksum changes

Sometimes it is preferable to avoid changes of exported symbol checksums
(to avoid breaking externally provided modules).  When a checksum change
occurs, it can be hard to figure out what caused this change: underlying
types may have changed, or additional type information may simply have
become available at the point where a symbol is exported.

Add a new --reference option to genksyms which allows it to report why
checksums change, based on the type information dumps it creates with the
--dump-types flag.  Genksyms will read in such a dump from a previous run,
and report which symbols have changed (and why).

The behavior can be controlled for an entire build as follows: If
KBUILD_SYMTYPES is set, genksyms uses --dump-types to produce *.symtypes
dump files.  If any *.symref files exist, those will be used as the
reference to check against.  If KBUILD_PRESERVE is set, checksum changes
will fail the build.

Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Cc: Randy Dunlap <randy.dunlap@oracle.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 468fbc9..d21f0ea 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -153,12 +153,18 @@
 
 quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@
 cmd_cc_symtypes_c	   = \
+		set -e;							\
 		$(CPP) -D__GENKSYMS__ $(c_flags) $<			\
-		| $(GENKSYMS) -T $@ >/dev/null;				\
+		| $(GENKSYMS) -T $@					\
+			      -r $(firstword $(wildcard			\
+				     $(@:.symtypes=.symref) /dev/null))	\
+			      $(if $(KBUILD_PRESERVE),-p)		\
+			      -a $(ARCH)				\
+		  >/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.
@@ -187,7 +193,11 @@
 	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)	\
+			           -T $(@:.o=.symtypes))		\
+			      -r $(firstword $(wildcard			\
+				     $(@:.o=.symref) /dev/null))	\
+			      $(if $(KBUILD_PRESERVE),-p)		\
+			      -a $(ARCH)				\
 		> $(@D)/.tmp_$(@F:.o=.ver);				\
 									\
 		$(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) 		\