Skip to content

Commit

Permalink
genksyms: allow to ignore symbol checksum changes
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Andreas Gruenbacher authored and Sam Ravnborg committed Dec 3, 2008
1 parent 64e6c1e commit 5dae9a5
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 4 deletions.
34 changes: 30 additions & 4 deletions scripts/genksyms/genksyms.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,26 @@ struct symbol *__add_symbol(const char *name, enum symbol_type type,
/* 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) {
status = is_unknown_symbol(sym) ?
STATUS_DEFINED : STATUS_MODIFIED;
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;
Expand Down Expand Up @@ -229,6 +244,7 @@ struct symbol *__add_symbol(const char *name, enum symbol_type type,

sym->is_declared = !is_reference;
sym->status = status;
sym->is_override = 0;

if (flag_debug) {
fprintf(debugfile, "Defn for %s %s == <",
Expand Down Expand Up @@ -348,9 +364,16 @@ static void read_reference(FILE *f)
while (!feof(f)) {
struct string_list *defn = NULL;
struct string_list *sym, *def;
int is_extern = 0;
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);
Expand All @@ -365,8 +388,9 @@ static void read_reference(FILE *f)
defn = def;
def = read_node(f);
}
add_reference_symbol(xstrdup(sym->string), sym->tag,
subsym = add_reference_symbol(xstrdup(sym->string), sym->tag,
defn, is_extern);
subsym->is_override = is_override;
free_node(sym);
}
}
Expand Down Expand Up @@ -743,6 +767,8 @@ int main(int argc, char **argv)
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);
Expand Down
1 change: 1 addition & 0 deletions scripts/genksyms/genksyms.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ struct symbol {
int is_extern;
int is_declared;
enum symbol_status status;
int is_override;
};

typedef struct string_list **yystype;
Expand Down

0 comments on commit 5dae9a5

Please sign in to comment.