1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Generate kernel symbol version hashes.
3 Copyright 1996, 1997 Linux International.
5 New implementation contributed by Richard Henderson <rth@tamu.edu>
6 Based on original work by Bjorn Ekwall <bj0rn@blox.se>
8 This file was part of the Linux modutils 2.4.22: moved back into the
9 kernel sources by Rusty Russell/Kai Germaschewski.
19 #ifdef __GNU_LIBRARY__
21 #endif /* __GNU_LIBRARY__ */
24 /*----------------------------------------------------------------------*/
26 #define HASH_BUCKETS 4096
28 static struct symbol *symtab[HASH_BUCKETS];
29 static FILE *debugfile;
35 static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
36 flag_preserve, flag_warnings, flag_rel_crcs;
41 static struct symbol *expansion_trail;
42 static struct symbol *visited_symbols;
48 [SYM_NORMAL] = { 0, NULL},
49 [SYM_TYPEDEF] = {'t', "typedef"},
50 [SYM_ENUM] = {'e', "enum"},
51 [SYM_STRUCT] = {'s', "struct"},
52 [SYM_UNION] = {'u', "union"},
53 [SYM_ENUM_CONST] = {'E', "enum constant"},
56 static int equal_list(struct string_list *a, struct string_list *b);
57 static void print_list(FILE * f, struct string_list *list);
58 static struct string_list *concat_list(struct string_list *start, ...);
59 static struct string_list *mk_node(const char *string);
60 static void print_location(void);
61 static void print_type_name(enum symbol_type type, const char *name);
63 /*----------------------------------------------------------------------*/
65 static const unsigned int crctab32[] = {
66 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U,
67 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U,
68 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U,
69 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU,
70 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U,
71 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U,
72 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U,
73 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU,
74 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U,
75 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU,
76 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U,
77 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
78 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U,
79 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU,
80 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU,
81 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U,
82 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU,
83 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U,
84 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U,
85 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U,
86 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU,
87 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U,
88 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U,
89 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
90 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U,
91 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U,
92 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U,
93 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
94 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U,
95 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU,
96 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU,
97 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U,
98 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U,
99 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU,
100 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU,
101 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
102 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU,
103 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U,
104 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU,
105 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U,
106 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU,
107 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
108 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U,
109 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU,
110 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U,
111 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U,
112 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U,
113 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
114 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U,
115 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U,
116 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU,
120 static unsigned long partial_crc32_one(unsigned char c, unsigned long crc)
122 return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
125 static unsigned long partial_crc32(const char *s, unsigned long crc)
128 crc = partial_crc32_one(*s++, crc);
132 static unsigned long crc32(const char *s)
134 return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
137 /*----------------------------------------------------------------------*/
139 static enum symbol_type map_to_ns(enum symbol_type t)
154 struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact)
156 unsigned long h = crc32(name) % HASH_BUCKETS;
159 for (sym = symtab[h]; sym; sym = sym->hash_next)
160 if (map_to_ns(sym->type) == map_to_ns(ns) &&
161 strcmp(name, sym->name) == 0 &&
165 if (exact && sym && sym->type != ns)
170 static int is_unknown_symbol(struct symbol *sym)
172 struct string_list *defn;
174 return ((sym->type == SYM_STRUCT ||
175 sym->type == SYM_UNION ||
176 sym->type == SYM_ENUM) &&
177 (defn = sym->defn) && defn->tag == SYM_NORMAL &&
178 strcmp(defn->string, "}") == 0 &&
179 (defn = defn->next) && defn->tag == SYM_NORMAL &&
180 strcmp(defn->string, "UNKNOWN") == 0 &&
181 (defn = defn->next) && defn->tag == SYM_NORMAL &&
182 strcmp(defn->string, "{") == 0);
185 static struct symbol *__add_symbol(const char *name, enum symbol_type type,
186 struct string_list *defn, int is_extern,
191 enum symbol_status status = STATUS_UNCHANGED;
192 /* The parser adds symbols in the order their declaration completes,
193 * so it is safe to store the value of the previous enum constant in
196 static int enum_counter;
197 static struct string_list *last_enum_expr;
199 if (type == SYM_ENUM_CONST) {
201 free_list(last_enum_expr, NULL);
202 last_enum_expr = copy_list_range(defn, NULL);
205 struct string_list *expr;
208 snprintf(buf, sizeof(buf), "%d", enum_counter++);
209 if (last_enum_expr) {
210 expr = copy_list_range(last_enum_expr, NULL);
211 defn = concat_list(mk_node("("),
220 } else if (type == SYM_ENUM) {
221 free_list(last_enum_expr, NULL);
222 last_enum_expr = NULL;
225 /* Anonymous enum definition, nothing more to do */
229 h = crc32(name) % HASH_BUCKETS;
230 for (sym = symtab[h]; sym; sym = sym->hash_next) {
231 if (map_to_ns(sym->type) == map_to_ns(type) &&
232 strcmp(name, sym->name) == 0) {
235 else if (sym->type == type &&
236 equal_list(sym->defn, defn)) {
237 if (!sym->is_declared && sym->is_override) {
239 print_type_name(type, name);
240 fprintf(stderr, " modversion is "
243 sym->is_declared = 1;
245 } else if (!sym->is_declared) {
246 if (sym->is_override && flag_preserve) {
248 fprintf(stderr, "ignoring ");
249 print_type_name(type, name);
250 fprintf(stderr, " modversion change\n");
251 sym->is_declared = 1;
254 status = is_unknown_symbol(sym) ?
255 STATUS_DEFINED : STATUS_MODIFIED;
258 error_with_pos("redefinition of %s", name);
266 struct symbol **psym;
268 for (psym = &symtab[h]; *psym; psym = &(*psym)->hash_next) {
270 *psym = sym->hash_next;
277 sym = xmalloc(sizeof(*sym));
281 sym->expansion_trail = NULL;
283 sym->is_extern = is_extern;
285 sym->hash_next = symtab[h];
288 sym->is_declared = !is_reference;
289 sym->status = status;
290 sym->is_override = 0;
293 if (symbol_types[type].name)
294 fprintf(debugfile, "Defn for %s %s == <",
295 symbol_types[type].name, name);
297 fprintf(debugfile, "Defn for type%d %s == <",
300 fputs("extern ", debugfile);
301 print_list(debugfile, defn);
302 fputs(">\n", debugfile);
309 struct symbol *add_symbol(const char *name, enum symbol_type type,
310 struct string_list *defn, int is_extern)
312 return __add_symbol(name, type, defn, is_extern, 0);
315 static struct symbol *add_reference_symbol(const char *name, enum symbol_type type,
316 struct string_list *defn, int is_extern)
318 return __add_symbol(name, type, defn, is_extern, 1);
321 /*----------------------------------------------------------------------*/
323 void free_node(struct string_list *node)
329 void free_list(struct string_list *s, struct string_list *e)
332 struct string_list *next = s->next;
338 static struct string_list *mk_node(const char *string)
340 struct string_list *newnode;
342 newnode = xmalloc(sizeof(*newnode));
343 newnode->string = xstrdup(string);
344 newnode->tag = SYM_NORMAL;
345 newnode->next = NULL;
350 static struct string_list *concat_list(struct string_list *start, ...)
353 struct string_list *n, *n2;
357 for (va_start(ap, start); (n = va_arg(ap, struct string_list *));) {
358 for (n2 = n; n2->next; n2 = n2->next)
367 struct string_list *copy_node(struct string_list *node)
369 struct string_list *newnode;
371 newnode = xmalloc(sizeof(*newnode));
372 newnode->string = xstrdup(node->string);
373 newnode->tag = node->tag;
378 struct string_list *copy_list_range(struct string_list *start,
379 struct string_list *end)
381 struct string_list *res, *n;
385 n = res = copy_node(start);
386 for (start = start->next; start != end; start = start->next) {
387 n->next = copy_node(start);
394 static int equal_list(struct string_list *a, struct string_list *b)
397 if (a->tag != b->tag || strcmp(a->string, b->string))
406 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
408 static struct string_list *read_node(FILE *f)
411 struct string_list node = {
414 int c, in_string = 0;
416 while ((c = fgetc(f)) != EOF) {
417 if (!in_string && c == ' ') {
418 if (node.string == buffer)
421 } else if (c == '"') {
422 in_string = !in_string;
423 } else if (c == '\n') {
424 if (node.string == buffer)
429 if (node.string >= buffer + sizeof(buffer) - 1) {
430 fprintf(stderr, "Token too long\n");
435 if (node.string == buffer)
438 node.string = buffer;
440 if (node.string[1] == '#') {
443 for (n = 0; n < ARRAY_SIZE(symbol_types); n++) {
444 if (node.string[0] == symbol_types[n].n) {
447 return copy_node(&node);
450 fprintf(stderr, "Unknown type %c\n", node.string[0]);
453 return copy_node(&node);
456 static void read_reference(FILE *f)
459 struct string_list *defn = NULL;
460 struct string_list *sym, *def;
461 int is_extern = 0, is_override = 0;
462 struct symbol *subsym;
465 if (sym && sym->tag == SYM_NORMAL &&
466 !strcmp(sym->string, "override")) {
474 if (def && def->tag == SYM_NORMAL &&
475 !strcmp(def->string, "extern")) {
485 subsym = add_reference_symbol(xstrdup(sym->string), sym->tag,
487 subsym->is_override = is_override;
492 static void print_node(FILE * f, struct string_list *list)
494 if (symbol_types[list->tag].n) {
495 putc(symbol_types[list->tag].n, f);
498 fputs(list->string, f);
501 static void print_list(FILE * f, struct string_list *list)
503 struct string_list **e, **b;
504 struct string_list *tmp, **tmp2;
513 while ((tmp = tmp->next) != NULL)
516 b = alloca(elem * sizeof(*e));
521 while ((list = list->next) != NULL)
530 static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
532 struct string_list *list = sym->defn;
533 struct string_list **e, **b;
534 struct string_list *tmp, **tmp2;
541 while ((tmp = tmp->next) != NULL)
544 b = alloca(elem * sizeof(*e));
549 while ((list = list->next) != NULL)
553 struct string_list *cur;
554 struct symbol *subsym;
560 fprintf(debugfile, "%s ", cur->string);
561 crc = partial_crc32(cur->string, crc);
562 crc = partial_crc32_one(' ', crc);
567 subsym = find_symbol(cur->string, cur->tag, 0);
568 /* FIXME: Bad reference files can segfault here. */
569 if (subsym->expansion_trail) {
571 fprintf(debugfile, "%s ", cur->string);
572 crc = partial_crc32(cur->string, crc);
573 crc = partial_crc32_one(' ', crc);
575 subsym->expansion_trail = expansion_trail;
576 expansion_trail = subsym;
577 crc = expand_and_crc_sym(subsym, crc);
584 subsym = find_symbol(cur->string, cur->tag, 0);
586 struct string_list *n;
588 error_with_pos("expand undefined %s %s",
589 symbol_types[cur->tag].name,
591 n = concat_list(mk_node
592 (symbol_types[cur->tag].name),
593 mk_node(cur->string),
598 add_symbol(cur->string, cur->tag, n, 0);
600 if (subsym->expansion_trail) {
601 if (flag_dump_defs) {
602 fprintf(debugfile, "%s %s ",
603 symbol_types[cur->tag].name,
607 crc = partial_crc32(symbol_types[cur->tag].name,
609 crc = partial_crc32_one(' ', crc);
610 crc = partial_crc32(cur->string, crc);
611 crc = partial_crc32_one(' ', crc);
613 subsym->expansion_trail = expansion_trail;
614 expansion_trail = subsym;
615 crc = expand_and_crc_sym(subsym, crc);
622 static struct symbol **end = &visited_symbols;
627 sym->visited = (struct symbol *)-1L;
634 void export_symbol(const char *name)
638 sym = find_symbol(name, SYM_NORMAL, 0);
640 error_with_pos("export undefined symbol %s", name);
646 fprintf(debugfile, "Export %s == <", name);
648 expansion_trail = (struct symbol *)-1L;
650 sym->expansion_trail = expansion_trail;
651 expansion_trail = sym;
652 crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff;
654 sym = expansion_trail;
655 while (sym != (struct symbol *)-1L) {
656 struct symbol *n = sym->expansion_trail;
658 if (sym->status != STATUS_UNCHANGED) {
661 fprintf(stderr, "%s: %s: modversion "
662 "changed because of changes "
663 "in ", flag_preserve ? "error" :
666 fprintf(stderr, ", ");
667 print_type_name(sym->type, sym->name);
668 if (sym->status == STATUS_DEFINED)
669 fprintf(stderr, " (became defined)");
674 sym->expansion_trail = 0;
678 fprintf(stderr, "\n");
681 fputs(">\n", debugfile);
683 /* Used as a linker script. */
684 printf(!flag_rel_crcs ? "__crc_%s = 0x%08lx;\n" :
685 "SECTIONS { .rodata : ALIGN(4) { "
686 "__crc_%s = .; LONG(0x%08lx); } }\n",
691 /*----------------------------------------------------------------------*/
693 static void print_location(void)
695 fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line);
698 static void print_type_name(enum symbol_type type, const char *name)
700 if (symbol_types[type].name)
701 fprintf(stderr, "%s %s", symbol_types[type].name, name);
703 fprintf(stderr, "%s", name);
706 void error_with_pos(const char *fmt, ...)
714 vfprintf(stderr, fmt, args);
722 static void genksyms_usage(void)
724 fputs("Usage:\n" "genksyms [-adDTwqhVR] > /path/to/.tmp_obj.ver\n" "\n"
725 #ifdef __GNU_LIBRARY__
726 " -s, --symbol-prefix Select symbol prefix\n"
727 " -d, --debug Increment the debug level (repeatable)\n"
728 " -D, --dump Dump expanded symbol defs (for debugging only)\n"
729 " -r, --reference file Read reference symbols from a file\n"
730 " -T, --dump-types file Dump expanded types into file\n"
731 " -p, --preserve Preserve reference modversions or fail\n"
732 " -w, --warnings Enable warnings\n"
733 " -q, --quiet Disable warnings (default)\n"
734 " -h, --help Print this message\n"
735 " -V, --version Print the release version\n"
736 " -R, --relative-crc Emit section relative symbol CRCs\n"
737 #else /* __GNU_LIBRARY__ */
738 " -s Select symbol prefix\n"
739 " -d Increment the debug level (repeatable)\n"
740 " -D Dump expanded symbol defs (for debugging only)\n"
741 " -r file Read reference symbols from a file\n"
742 " -T file Dump expanded types into file\n"
743 " -p Preserve reference modversions or fail\n"
744 " -w Enable warnings\n"
745 " -q Disable warnings (default)\n"
746 " -h Print this message\n"
747 " -V Print the release version\n"
748 " -R Emit section relative symbol CRCs\n"
749 #endif /* __GNU_LIBRARY__ */
753 int main(int argc, char **argv)
755 FILE *dumpfile = NULL, *ref_file = NULL;
758 #ifdef __GNU_LIBRARY__
759 struct option long_opts[] = {
760 {"debug", 0, 0, 'd'},
761 {"warnings", 0, 0, 'w'},
762 {"quiet", 0, 0, 'q'},
764 {"reference", 1, 0, 'r'},
765 {"dump-types", 1, 0, 'T'},
766 {"preserve", 0, 0, 'p'},
767 {"version", 0, 0, 'V'},
769 {"relative-crc", 0, 0, 'R'},
773 while ((o = getopt_long(argc, argv, "s:dwqVDr:T:phR",
774 &long_opts[0], NULL)) != EOF)
775 #else /* __GNU_LIBRARY__ */
776 while ((o = getopt(argc, argv, "s:dwqVDr:T:phR")) != EOF)
777 #endif /* __GNU_LIBRARY__ */
789 fputs("genksyms version 2.5.60\n", stderr);
796 ref_file = fopen(optarg, "r");
804 dumpfile = fopen(optarg, "w");
825 extern int yy_flex_debug;
827 yydebug = (flag_debug > 1);
828 yy_flex_debug = (flag_debug > 2);
831 /* setlinebuf(debugfile); */
834 if (flag_reference) {
835 read_reference(ref_file);
841 if (flag_dump_types && visited_symbols) {
842 while (visited_symbols != (struct symbol *)-1L) {
843 struct symbol *sym = visited_symbols;
845 if (sym->is_override)
846 fputs("override ", dumpfile);
847 if (symbol_types[sym->type].n) {
848 putc(symbol_types[sym->type].n, dumpfile);
851 fputs(sym->name, dumpfile);
854 fputs("extern ", dumpfile);
855 print_list(dumpfile, sym->defn);
856 putc('\n', dumpfile);
858 visited_symbols = sym->visited;
864 fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
866 (double)nsyms / (double)HASH_BUCKETS);