Commit 5dae9a550a7478c8d6a7da2336d3ceeebf90ab84
Committed by
Sam Ravnborg
1 parent
64e6c1e123
Exists in
master
and in
20 other branches
genksyms: allow to ignore symbol checksum changes
This adds an "override" keyword for use in *.symvers / *.symref files. When a symbol is overridden, the symbol's old definition will be used for computing checksums instead of the new one, preserving the previous checksum. (Genksyms will still warn about the change.) This is meant to allow distributions to hide minor actual as well as fake ABI changes. (For example, when extra type information becomes available because additional headers are included, this may change checksums even though none of the types used have actully changed.) This approach also allows to get rid of "#ifdef __GENKSYMS__" hacks in the code, which are currently used in some vendor kernels to work around checksum changes. 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>
Showing 2 changed files with 31 additions and 4 deletions Side-by-side Diff
scripts/genksyms/genksyms.c
... | ... | @@ -191,11 +191,26 @@ |
191 | 191 | /* fall through */ ; |
192 | 192 | else if (sym->type == type && |
193 | 193 | equal_list(sym->defn, defn)) { |
194 | + if (!sym->is_declared && sym->is_override) { | |
195 | + print_location(); | |
196 | + print_type_name(type, name); | |
197 | + fprintf(stderr, " modversion is " | |
198 | + "unchanged\n"); | |
199 | + } | |
194 | 200 | sym->is_declared = 1; |
195 | 201 | return sym; |
196 | 202 | } else if (!sym->is_declared) { |
197 | - status = is_unknown_symbol(sym) ? | |
198 | - STATUS_DEFINED : STATUS_MODIFIED; | |
203 | + if (sym->is_override && flag_preserve) { | |
204 | + print_location(); | |
205 | + fprintf(stderr, "ignoring "); | |
206 | + print_type_name(type, name); | |
207 | + fprintf(stderr, " modversion change\n"); | |
208 | + sym->is_declared = 1; | |
209 | + return sym; | |
210 | + } else { | |
211 | + status = is_unknown_symbol(sym) ? | |
212 | + STATUS_DEFINED : STATUS_MODIFIED; | |
213 | + } | |
199 | 214 | } else { |
200 | 215 | error_with_pos("redefinition of %s", name); |
201 | 216 | return sym; |
... | ... | @@ -229,6 +244,7 @@ |
229 | 244 | |
230 | 245 | sym->is_declared = !is_reference; |
231 | 246 | sym->status = status; |
247 | + sym->is_override = 0; | |
232 | 248 | |
233 | 249 | if (flag_debug) { |
234 | 250 | fprintf(debugfile, "Defn for %s %s == <", |
235 | 251 | |
... | ... | @@ -348,9 +364,16 @@ |
348 | 364 | while (!feof(f)) { |
349 | 365 | struct string_list *defn = NULL; |
350 | 366 | struct string_list *sym, *def; |
351 | - int is_extern = 0; | |
367 | + int is_extern = 0, is_override = 0; | |
368 | + struct symbol *subsym; | |
352 | 369 | |
353 | 370 | sym = read_node(f); |
371 | + if (sym && sym->tag == SYM_NORMAL && | |
372 | + !strcmp(sym->string, "override")) { | |
373 | + is_override = 1; | |
374 | + free_node(sym); | |
375 | + sym = read_node(f); | |
376 | + } | |
354 | 377 | if (!sym) |
355 | 378 | continue; |
356 | 379 | def = read_node(f); |
357 | 380 | |
... | ... | @@ -365,8 +388,9 @@ |
365 | 388 | defn = def; |
366 | 389 | def = read_node(f); |
367 | 390 | } |
368 | - add_reference_symbol(xstrdup(sym->string), sym->tag, | |
391 | + subsym = add_reference_symbol(xstrdup(sym->string), sym->tag, | |
369 | 392 | defn, is_extern); |
393 | + subsym->is_override = is_override; | |
370 | 394 | free_node(sym); |
371 | 395 | } |
372 | 396 | } |
... | ... | @@ -743,6 +767,8 @@ |
743 | 767 | while (visited_symbols != (struct symbol *)-1L) { |
744 | 768 | struct symbol *sym = visited_symbols; |
745 | 769 | |
770 | + if (sym->is_override) | |
771 | + fputs("override ", dumpfile); | |
746 | 772 | if (sym->type != SYM_NORMAL) { |
747 | 773 | putc(symbol_type_name[sym->type][0], dumpfile); |
748 | 774 | putc('#', dumpfile); |