Commit 5dae9a55 authored by Andreas Gruenbacher's avatar Andreas Gruenbacher Committed by Sam Ravnborg

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: default avatarAndreas Gruenbacher <agruen@suse.de>
Cc: Randy Dunlap <randy.dunlap@oracle.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarSam Ravnborg <sam@ravnborg.org>
parent 64e6c1e1
...@@ -191,11 +191,26 @@ struct symbol *__add_symbol(const char *name, enum symbol_type type, ...@@ -191,11 +191,26 @@ struct symbol *__add_symbol(const char *name, enum symbol_type type,
/* fall through */ ; /* fall through */ ;
else if (sym->type == type && else if (sym->type == type &&
equal_list(sym->defn, defn)) { 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; sym->is_declared = 1;
return sym; return sym;
} else if (!sym->is_declared) { } else if (!sym->is_declared) {
status = is_unknown_symbol(sym) ? if (sym->is_override && flag_preserve) {
STATUS_DEFINED : STATUS_MODIFIED; 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 { } else {
error_with_pos("redefinition of %s", name); error_with_pos("redefinition of %s", name);
return sym; return sym;
...@@ -229,6 +244,7 @@ struct symbol *__add_symbol(const char *name, enum symbol_type type, ...@@ -229,6 +244,7 @@ struct symbol *__add_symbol(const char *name, enum symbol_type type,
sym->is_declared = !is_reference; sym->is_declared = !is_reference;
sym->status = status; sym->status = status;
sym->is_override = 0;
if (flag_debug) { if (flag_debug) {
fprintf(debugfile, "Defn for %s %s == <", fprintf(debugfile, "Defn for %s %s == <",
...@@ -348,9 +364,16 @@ static void read_reference(FILE *f) ...@@ -348,9 +364,16 @@ static void read_reference(FILE *f)
while (!feof(f)) { while (!feof(f)) {
struct string_list *defn = NULL; struct string_list *defn = NULL;
struct string_list *sym, *def; struct string_list *sym, *def;
int is_extern = 0; int is_extern = 0, is_override = 0;
struct symbol *subsym;
sym = read_node(f); 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) if (!sym)
continue; continue;
def = read_node(f); def = read_node(f);
...@@ -365,8 +388,9 @@ static void read_reference(FILE *f) ...@@ -365,8 +388,9 @@ static void read_reference(FILE *f)
defn = def; defn = def;
def = read_node(f); def = read_node(f);
} }
add_reference_symbol(xstrdup(sym->string), sym->tag, subsym = add_reference_symbol(xstrdup(sym->string), sym->tag,
defn, is_extern); defn, is_extern);
subsym->is_override = is_override;
free_node(sym); free_node(sym);
} }
} }
...@@ -743,6 +767,8 @@ int main(int argc, char **argv) ...@@ -743,6 +767,8 @@ int main(int argc, char **argv)
while (visited_symbols != (struct symbol *)-1L) { while (visited_symbols != (struct symbol *)-1L) {
struct symbol *sym = visited_symbols; struct symbol *sym = visited_symbols;
if (sym->is_override)
fputs("override ", dumpfile);
if (sym->type != SYM_NORMAL) { if (sym->type != SYM_NORMAL) {
putc(symbol_type_name[sym->type][0], dumpfile); putc(symbol_type_name[sym->type][0], dumpfile);
putc('#', dumpfile); putc('#', dumpfile);
......
...@@ -49,6 +49,7 @@ struct symbol { ...@@ -49,6 +49,7 @@ struct symbol {
int is_extern; int is_extern;
int is_declared; int is_declared;
enum symbol_status status; enum symbol_status status;
int is_override;
}; };
typedef struct string_list **yystype; typedef struct string_list **yystype;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment