From: Andreas Gruenbacher <agruen@suse.de>
Subject: genksyms: add --override flag
Patch-mainline: Not yet, <jeffm: asked msuchanek to submit, Oct 4, 2017>
References: none

Add --override flag to genksyms to allow overriding types with old
definitions using the 'override' keyword. This is similar to -p --preserve,
but it doesn't abort the build if a symtype cannot be preserved

[mmarek: added KBUILD_OVERRIDE env var to set this globally for the entire
 build]
---
 scripts/Makefile.build      |  1 +
 scripts/genksyms/genksyms.c | 21 +++++++++++++++------
 2 files changed, 16 insertions(+), 6 deletions(-)

--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -129,6 +129,7 @@ $(obj)/%.i: $(src)/%.c FORCE
 genksyms = scripts/genksyms/genksyms		\
 	$(if $(1), -T $(2))			\
 	$(if $(KBUILD_PRESERVE), -p)		\
+	$(if $(KBUILD_OVERRIDE),-o)		\
 	-r $(or $(wildcard $(2:.symtypes=.symref)), /dev/null)
 
 # These mirror gensymtypes_S and co below, keep them in synch.
--- a/scripts/genksyms/genksyms.c
+++ b/scripts/genksyms/genksyms.c
@@ -33,7 +33,7 @@ char *cur_filename;
 int in_source_file;
 
 static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
-	   flag_preserve, flag_warnings;
+	   flag_override, flag_preserve, flag_warnings;
 
 static int errors;
 static int nsyms;
@@ -243,7 +243,7 @@ static struct symbol *__add_symbol(const char *name, enum symbol_type type,
 				sym->is_declared = 1;
 				return sym;
 			} else if (!sym->is_declared) {
-				if (sym->is_override && flag_preserve) {
+				if (sym->is_override && flag_override) {
 					print_location();
 					fprintf(stderr, "ignoring ");
 					print_type_name(type, name);
@@ -656,11 +656,13 @@ void export_symbol(const char *name)
 			struct symbol *n = sym->expansion_trail;
 
 			if (sym->status != STATUS_UNCHANGED) {
+				int fail = sym->is_override && flag_preserve;
+
 				if (!has_changed) {
 					print_location();
 					fprintf(stderr, "%s: %s: modversion "
 						"changed because of changes "
-						"in ", flag_preserve ? "error" :
+						"in ", fail ? "error" :
 						       "warning", name);
 				} else
 					fprintf(stderr, ", ");
@@ -668,7 +670,7 @@ void export_symbol(const char *name)
 				if (sym->status == STATUS_DEFINED)
 					fprintf(stderr, " (became defined)");
 				has_changed = 1;
-				if (flag_preserve)
+				if (fail)
 					errors++;
 			}
 			sym->expansion_trail = 0;
@@ -724,6 +726,7 @@ static void genksyms_usage(void)
 	      "  -D, --dump            Dump expanded symbol defs (for debugging only)\n"
 	      "  -r, --reference file  Read reference symbols from a file\n"
 	      "  -T, --dump-types file Dump expanded types into file\n"
+	      "  -o, --override        Allow to override reference modversions\n"
 	      "  -p, --preserve        Preserve reference modversions or fail\n"
 	      "  -w, --warnings        Enable warnings\n"
 	      "  -q, --quiet           Disable warnings (default)\n"
@@ -735,6 +738,7 @@ static void genksyms_usage(void)
 	      "  -D                    Dump expanded symbol defs (for debugging only)\n"
 	      "  -r file               Read reference symbols from a file\n"
 	      "  -T file               Dump expanded types into file\n"
+	      "  -o                    Allow to override reference modversions\n"
 	      "  -p                    Preserve reference modversions or fail\n"
 	      "  -w                    Enable warnings\n"
 	      "  -q                    Disable warnings (default)\n"
@@ -758,15 +762,16 @@ int main(int argc, char **argv)
 		{"reference", 1, 0, 'r'},
 		{"dump-types", 1, 0, 'T'},
 		{"preserve", 0, 0, 'p'},
+		{"override", 0, 0, 'o'},
 		{"version", 0, 0, 'V'},
 		{"help", 0, 0, 'h'},
 		{0, 0, 0, 0}
 	};
 
-	while ((o = getopt_long(argc, argv, "s:dwqVDr:T:ph",
+	while ((o = getopt_long(argc, argv, "s:dwqVDr:T:oph",
 				&long_opts[0], NULL)) != EOF)
 #else				/* __GNU_LIBRARY__ */
-	while ((o = getopt(argc, argv, "s:dwqVDr:T:ph")) != EOF)
+	while ((o = getopt(argc, argv, "s:dwqVDr:T:oph")) != EOF)
 #endif				/* __GNU_LIBRARY__ */
 		switch (o) {
 		case 'd':
@@ -800,7 +805,11 @@ int main(int argc, char **argv)
 				return 1;
 			}
 			break;
+		case 'o':
+			flag_override = 1;
+			break;
 		case 'p':
+			flag_override = 1;
 			flag_preserve = 1;
 			break;
 		case 'h':
