1 /* Generate kernel symbol version hashes.
2 Copyright 1996, 1997 Linux International.
4 New implementation contributed by Richard Henderson <rth@tamu.edu>
5 Based on original work by Bjorn Ekwall <bj0rn@blox.se>
7 This file was part of the Linux modutils 2.4.22: moved back into the
8 kernel sources by Rusty Russell/Kai Germaschewski.
10 This program is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2 of the License, or (at your
13 option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software Foundation,
22 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
30 #ifdef __GNU_LIBRARY__
32 #endif /* __GNU_LIBRARY__ */
35 /*----------------------------------------------------------------------*/
37 #define HASH_BUCKETS 4096
39 static struct symbol *symtab[HASH_BUCKETS];
40 static FILE *debugfile;
43 char *cur_filename, *source_file;
46 static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
47 flag_preserve, flag_warnings, flag_rel_crcs;
52 static struct symbol *expansion_trail;
53 static struct symbol *visited_symbols;
59 [SYM_NORMAL] = { 0, NULL},
60 [SYM_TYPEDEF] = {'t', "typedef"},
61 [SYM_ENUM] = {'e', "enum"},
62 [SYM_STRUCT] = {'s', "struct"},
63 [SYM_UNION] = {'u', "union"},
64 [SYM_ENUM_CONST] = {'E', "enum constant"},
67 static int equal_list(struct string_list *a, struct string_list *b);
68 static void print_list(FILE * f, struct string_list *list);
69 static struct string_list *concat_list(struct string_list *start, ...);
70 static struct string_list *mk_node(const char *string);
71 static void print_location(void);
72 static void print_type_name(enum symbol_type type, const char *name);
74 /*----------------------------------------------------------------------*/
76 static const unsigned int crctab32[] = {
77 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U,
78 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U,
79 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U,
80 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU,
81 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U,
82 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U,
83 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U,
84 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU,
85 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U,
86 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU,
87 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U,
88 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
89 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U,
90 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU,
91 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU,
92 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U,
93 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU,
94 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U,
95 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U,
96 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U,
97 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU,
98 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U,
99 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U,
100 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
101 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U,
102 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U,
103 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U,
104 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
105 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U,
106 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU,
107 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU,
108 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U,
109 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U,
110 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU,
111 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU,
112 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
113 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU,
114 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U,
115 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU,
116 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U,
117 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU,
118 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
119 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U,
120 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU,
121 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U,
122 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U,
123 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U,
124 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
125 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U,
126 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U,
127 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU,
131 static unsigned long partial_crc32_one(unsigned char c, unsigned long crc)
133 return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
136 static unsigned long partial_crc32(const char *s, unsigned long crc)
139 crc = partial_crc32_one(*s++, crc);
143 static unsigned long crc32(const char *s)
145 return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
148 /*----------------------------------------------------------------------*/
150 static enum symbol_type map_to_ns(enum symbol_type t)
165 struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact)
167 unsigned long h = crc32(name) % HASH_BUCKETS;
170 for (sym = symtab[h]; sym; sym = sym->hash_next)
171 if (map_to_ns(sym->type) == map_to_ns(ns) &&
172 strcmp(name, sym->name) == 0 &&
176 if (exact && sym && sym->type != ns)
181 static int is_unknown_symbol(struct symbol *sym)
183 struct string_list *defn;
185 return ((sym->type == SYM_STRUCT ||
186 sym->type == SYM_UNION ||
187 sym->type == SYM_ENUM) &&
188 (defn = sym->defn) && defn->tag == SYM_NORMAL &&
189 strcmp(defn->string, "}") == 0 &&
190 (defn = defn->next) && defn->tag == SYM_NORMAL &&
191 strcmp(defn->string, "UNKNOWN") == 0 &&
192 (defn = defn->next) && defn->tag == SYM_NORMAL &&
193 strcmp(defn->string, "{") == 0);
196 static struct symbol *__add_symbol(const char *name, enum symbol_type type,
197 struct string_list *defn, int is_extern,
202 enum symbol_status status = STATUS_UNCHANGED;
203 /* The parser adds symbols in the order their declaration completes,
204 * so it is safe to store the value of the previous enum constant in
207 static int enum_counter;
208 static struct string_list *last_enum_expr;
210 if (type == SYM_ENUM_CONST) {
212 free_list(last_enum_expr, NULL);
213 last_enum_expr = copy_list_range(defn, NULL);
216 struct string_list *expr;
219 snprintf(buf, sizeof(buf), "%d", enum_counter++);
220 if (last_enum_expr) {
221 expr = copy_list_range(last_enum_expr, NULL);
222 defn = concat_list(mk_node("("),
231 } else if (type == SYM_ENUM) {
232 free_list(last_enum_expr, NULL);
233 last_enum_expr = NULL;
236 /* Anonymous enum definition, nothing more to do */
240 h = crc32(name) % HASH_BUCKETS;
241 for (sym = symtab[h]; sym; sym = sym->hash_next) {
242 if (map_to_ns(sym->type) == map_to_ns(type) &&
243 strcmp(name, sym->name) == 0) {
246 else if (sym->type == type &&
247 equal_list(sym->defn, defn)) {
248 if (!sym->is_declared && sym->is_override) {
250 print_type_name(type, name);
251 fprintf(stderr, " modversion is "
254 sym->is_declared = 1;
256 } else if (!sym->is_declared) {
257 if (sym->is_override && flag_preserve) {
259 fprintf(stderr, "ignoring ");
260 print_type_name(type, name);
261 fprintf(stderr, " modversion change\n");
262 sym->is_declared = 1;
265 status = is_unknown_symbol(sym) ?
266 STATUS_DEFINED : STATUS_MODIFIED;
269 error_with_pos("redefinition of %s", name);
277 struct symbol **psym;
279 for (psym = &symtab[h]; *psym; psym = &(*psym)->hash_next) {
281 *psym = sym->hash_next;
288 sym = xmalloc(sizeof(*sym));
292 sym->expansion_trail = NULL;
294 sym->is_extern = is_extern;
296 sym->hash_next = symtab[h];
299 sym->is_declared = !is_reference;
300 sym->status = status;
301 sym->is_override = 0;
304 if (symbol_types[type].name)
305 fprintf(debugfile, "Defn for %s %s == <",
306 symbol_types[type].name, name);
308 fprintf(debugfile, "Defn for type%d %s == <",
311 fputs("extern ", debugfile);
312 print_list(debugfile, defn);
313 fputs(">\n", debugfile);
320 struct symbol *add_symbol(const char *name, enum symbol_type type,
321 struct string_list *defn, int is_extern)
323 return __add_symbol(name, type, defn, is_extern, 0);
326 static struct symbol *add_reference_symbol(const char *name, enum symbol_type type,
327 struct string_list *defn, int is_extern)
329 return __add_symbol(name, type, defn, is_extern, 1);
332 /*----------------------------------------------------------------------*/
334 void free_node(struct string_list *node)
340 void free_list(struct string_list *s, struct string_list *e)
343 struct string_list *next = s->next;
349 static struct string_list *mk_node(const char *string)
351 struct string_list *newnode;
353 newnode = xmalloc(sizeof(*newnode));
354 newnode->string = xstrdup(string);
355 newnode->tag = SYM_NORMAL;
356 newnode->next = NULL;
361 static struct string_list *concat_list(struct string_list *start, ...)
364 struct string_list *n, *n2;
368 for (va_start(ap, start); (n = va_arg(ap, struct string_list *));) {
369 for (n2 = n; n2->next; n2 = n2->next)
378 struct string_list *copy_node(struct string_list *node)
380 struct string_list *newnode;
382 newnode = xmalloc(sizeof(*newnode));
383 newnode->string = xstrdup(node->string);
384 newnode->tag = node->tag;
389 struct string_list *copy_list_range(struct string_list *start,
390 struct string_list *end)
392 struct string_list *res, *n;
396 n = res = copy_node(start);
397 for (start = start->next; start != end; start = start->next) {
398 n->next = copy_node(start);
405 static int equal_list(struct string_list *a, struct string_list *b)
408 if (a->tag != b->tag || strcmp(a->string, b->string))
417 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
419 static struct string_list *read_node(FILE *f)
422 struct string_list node = {
425 int c, in_string = 0;
427 while ((c = fgetc(f)) != EOF) {
428 if (!in_string && c == ' ') {
429 if (node.string == buffer)
432 } else if (c == '"') {
433 in_string = !in_string;
434 } else if (c == '\n') {
435 if (node.string == buffer)
440 if (node.string >= buffer + sizeof(buffer) - 1) {
441 fprintf(stderr, "Token too long\n");
446 if (node.string == buffer)
449 node.string = buffer;
451 if (node.string[1] == '#') {
454 for (n = 0; n < ARRAY_SIZE(symbol_types); n++) {
455 if (node.string[0] == symbol_types[n].n) {
458 return copy_node(&node);
461 fprintf(stderr, "Unknown type %c\n", node.string[0]);
464 return copy_node(&node);
467 static void read_reference(FILE *f)
470 struct string_list *defn = NULL;
471 struct string_list *sym, *def;
472 int is_extern = 0, is_override = 0;
473 struct symbol *subsym;
476 if (sym && sym->tag == SYM_NORMAL &&
477 !strcmp(sym->string, "override")) {
485 if (def && def->tag == SYM_NORMAL &&
486 !strcmp(def->string, "extern")) {
496 subsym = add_reference_symbol(xstrdup(sym->string), sym->tag,
498 subsym->is_override = is_override;
503 static void print_node(FILE * f, struct string_list *list)
505 if (symbol_types[list->tag].n) {
506 putc(symbol_types[list->tag].n, f);
509 fputs(list->string, f);
512 static void print_list(FILE * f, struct string_list *list)
514 struct string_list **e, **b;
515 struct string_list *tmp, **tmp2;
524 while ((tmp = tmp->next) != NULL)
527 b = alloca(elem * sizeof(*e));
532 while ((list = list->next) != NULL)
541 static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
543 struct string_list *list = sym->defn;
544 struct string_list **e, **b;
545 struct string_list *tmp, **tmp2;
552 while ((tmp = tmp->next) != NULL)
555 b = alloca(elem * sizeof(*e));
560 while ((list = list->next) != NULL)
564 struct string_list *cur;
565 struct symbol *subsym;
571 fprintf(debugfile, "%s ", cur->string);
572 crc = partial_crc32(cur->string, crc);
573 crc = partial_crc32_one(' ', crc);
578 subsym = find_symbol(cur->string, cur->tag, 0);
579 /* FIXME: Bad reference files can segfault here. */
580 if (subsym->expansion_trail) {
582 fprintf(debugfile, "%s ", cur->string);
583 crc = partial_crc32(cur->string, crc);
584 crc = partial_crc32_one(' ', crc);
586 subsym->expansion_trail = expansion_trail;
587 expansion_trail = subsym;
588 crc = expand_and_crc_sym(subsym, crc);
595 subsym = find_symbol(cur->string, cur->tag, 0);
597 struct string_list *n;
599 error_with_pos("expand undefined %s %s",
600 symbol_types[cur->tag].name,
602 n = concat_list(mk_node
603 (symbol_types[cur->tag].name),
604 mk_node(cur->string),
609 add_symbol(cur->string, cur->tag, n, 0);
611 if (subsym->expansion_trail) {
612 if (flag_dump_defs) {
613 fprintf(debugfile, "%s %s ",
614 symbol_types[cur->tag].name,
618 crc = partial_crc32(symbol_types[cur->tag].name,
620 crc = partial_crc32_one(' ', crc);
621 crc = partial_crc32(cur->string, crc);
622 crc = partial_crc32_one(' ', crc);
624 subsym->expansion_trail = expansion_trail;
625 expansion_trail = subsym;
626 crc = expand_and_crc_sym(subsym, crc);
633 static struct symbol **end = &visited_symbols;
638 sym->visited = (struct symbol *)-1L;
645 void export_symbol(const char *name)
649 sym = find_symbol(name, SYM_NORMAL, 0);
651 error_with_pos("export undefined symbol %s", name);
657 fprintf(debugfile, "Export %s == <", name);
659 expansion_trail = (struct symbol *)-1L;
661 sym->expansion_trail = expansion_trail;
662 expansion_trail = sym;
663 crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff;
665 sym = expansion_trail;
666 while (sym != (struct symbol *)-1L) {
667 struct symbol *n = sym->expansion_trail;
669 if (sym->status != STATUS_UNCHANGED) {
672 fprintf(stderr, "%s: %s: modversion "
673 "changed because of changes "
674 "in ", flag_preserve ? "error" :
677 fprintf(stderr, ", ");
678 print_type_name(sym->type, sym->name);
679 if (sym->status == STATUS_DEFINED)
680 fprintf(stderr, " (became defined)");
685 sym->expansion_trail = 0;
689 fprintf(stderr, "\n");
692 fputs(">\n", debugfile);
694 /* Used as a linker script. */
695 printf(!flag_rel_crcs ? "__crc_%s = 0x%08lx;\n" :
696 "SECTIONS { .rodata : ALIGN(4) { "
697 "__crc_%s = .; LONG(0x%08lx); } }\n",
702 /*----------------------------------------------------------------------*/
704 static void print_location(void)
706 fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line);
709 static void print_type_name(enum symbol_type type, const char *name)
711 if (symbol_types[type].name)
712 fprintf(stderr, "%s %s", symbol_types[type].name, name);
714 fprintf(stderr, "%s", name);
717 void error_with_pos(const char *fmt, ...)
725 vfprintf(stderr, fmt, args);
733 static void genksyms_usage(void)
735 fputs("Usage:\n" "genksyms [-adDTwqhVR] > /path/to/.tmp_obj.ver\n" "\n"
736 #ifdef __GNU_LIBRARY__
737 " -s, --symbol-prefix Select symbol prefix\n"
738 " -d, --debug Increment the debug level (repeatable)\n"
739 " -D, --dump Dump expanded symbol defs (for debugging only)\n"
740 " -r, --reference file Read reference symbols from a file\n"
741 " -T, --dump-types file Dump expanded types into file\n"
742 " -p, --preserve Preserve reference modversions or fail\n"
743 " -w, --warnings Enable warnings\n"
744 " -q, --quiet Disable warnings (default)\n"
745 " -h, --help Print this message\n"
746 " -V, --version Print the release version\n"
747 " -R, --relative-crc Emit section relative symbol CRCs\n"
748 #else /* __GNU_LIBRARY__ */
749 " -s Select symbol prefix\n"
750 " -d Increment the debug level (repeatable)\n"
751 " -D Dump expanded symbol defs (for debugging only)\n"
752 " -r file Read reference symbols from a file\n"
753 " -T file Dump expanded types into file\n"
754 " -p Preserve reference modversions or fail\n"
755 " -w Enable warnings\n"
756 " -q Disable warnings (default)\n"
757 " -h Print this message\n"
758 " -V Print the release version\n"
759 " -R Emit section relative symbol CRCs\n"
760 #endif /* __GNU_LIBRARY__ */
764 int main(int argc, char **argv)
766 FILE *dumpfile = NULL, *ref_file = NULL;
769 #ifdef __GNU_LIBRARY__
770 struct option long_opts[] = {
771 {"debug", 0, 0, 'd'},
772 {"warnings", 0, 0, 'w'},
773 {"quiet", 0, 0, 'q'},
775 {"reference", 1, 0, 'r'},
776 {"dump-types", 1, 0, 'T'},
777 {"preserve", 0, 0, 'p'},
778 {"version", 0, 0, 'V'},
780 {"relative-crc", 0, 0, 'R'},
784 while ((o = getopt_long(argc, argv, "s:dwqVDr:T:phR",
785 &long_opts[0], NULL)) != EOF)
786 #else /* __GNU_LIBRARY__ */
787 while ((o = getopt(argc, argv, "s:dwqVDr:T:phR")) != EOF)
788 #endif /* __GNU_LIBRARY__ */
800 fputs("genksyms version 2.5.60\n", stderr);
807 ref_file = fopen(optarg, "r");
815 dumpfile = fopen(optarg, "w");
836 extern int yy_flex_debug;
838 yydebug = (flag_debug > 1);
839 yy_flex_debug = (flag_debug > 2);
842 /* setlinebuf(debugfile); */
845 if (flag_reference) {
846 read_reference(ref_file);
852 if (flag_dump_types && visited_symbols) {
853 while (visited_symbols != (struct symbol *)-1L) {
854 struct symbol *sym = visited_symbols;
856 if (sym->is_override)
857 fputs("override ", dumpfile);
858 if (symbol_types[sym->type].n) {
859 putc(symbol_types[sym->type].n, dumpfile);
862 fputs(sym->name, dumpfile);
865 fputs("extern ", dumpfile);
866 print_list(dumpfile, sym->defn);
867 putc('\n', dumpfile);
869 visited_symbols = sym->visited;
875 fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
877 (double)nsyms / (double)HASH_BUCKETS);