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;
48 static const char *arch = "";
49 static const char *mod_prefix = "";
54 static struct symbol *expansion_trail;
55 static struct symbol *visited_symbols;
61 [SYM_NORMAL] = { 0, NULL},
62 [SYM_TYPEDEF] = {'t', "typedef"},
63 [SYM_ENUM] = {'e', "enum"},
64 [SYM_STRUCT] = {'s', "struct"},
65 [SYM_UNION] = {'u', "union"},
66 [SYM_ENUM_CONST] = {'E', "enum constant"},
69 static int equal_list(struct string_list *a, struct string_list *b);
70 static void print_list(FILE * f, struct string_list *list);
71 static struct string_list *concat_list(struct string_list *start, ...);
72 static struct string_list *mk_node(const char *string);
73 static void print_location(void);
74 static void print_type_name(enum symbol_type type, const char *name);
76 /*----------------------------------------------------------------------*/
78 static const unsigned int crctab32[] = {
79 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U,
80 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U,
81 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U,
82 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU,
83 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U,
84 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U,
85 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U,
86 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU,
87 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U,
88 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU,
89 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U,
90 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
91 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U,
92 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU,
93 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU,
94 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U,
95 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU,
96 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U,
97 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U,
98 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U,
99 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU,
100 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U,
101 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U,
102 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
103 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U,
104 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U,
105 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U,
106 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
107 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U,
108 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU,
109 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU,
110 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U,
111 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U,
112 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU,
113 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU,
114 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
115 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU,
116 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U,
117 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU,
118 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U,
119 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU,
120 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
121 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U,
122 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU,
123 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U,
124 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U,
125 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U,
126 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
127 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U,
128 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U,
129 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU,
133 static unsigned long partial_crc32_one(unsigned char c, unsigned long crc)
135 return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
138 static unsigned long partial_crc32(const char *s, unsigned long crc)
141 crc = partial_crc32_one(*s++, crc);
145 static unsigned long crc32(const char *s)
147 return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
150 /*----------------------------------------------------------------------*/
152 static enum symbol_type map_to_ns(enum symbol_type t)
167 struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact)
169 unsigned long h = crc32(name) % HASH_BUCKETS;
172 for (sym = symtab[h]; sym; sym = sym->hash_next)
173 if (map_to_ns(sym->type) == map_to_ns(ns) &&
174 strcmp(name, sym->name) == 0 &&
178 if (exact && sym && sym->type != ns)
183 static int is_unknown_symbol(struct symbol *sym)
185 struct string_list *defn;
187 return ((sym->type == SYM_STRUCT ||
188 sym->type == SYM_UNION ||
189 sym->type == SYM_ENUM) &&
190 (defn = sym->defn) && defn->tag == SYM_NORMAL &&
191 strcmp(defn->string, "}") == 0 &&
192 (defn = defn->next) && defn->tag == SYM_NORMAL &&
193 strcmp(defn->string, "UNKNOWN") == 0 &&
194 (defn = defn->next) && defn->tag == SYM_NORMAL &&
195 strcmp(defn->string, "{") == 0);
198 static struct symbol *__add_symbol(const char *name, enum symbol_type type,
199 struct string_list *defn, int is_extern,
204 enum symbol_status status = STATUS_UNCHANGED;
205 /* The parser adds symbols in the order their declaration completes,
206 * so it is safe to store the value of the previous enum constant in
209 static int enum_counter;
210 static struct string_list *last_enum_expr;
212 if (type == SYM_ENUM_CONST) {
214 free_list(last_enum_expr, NULL);
215 last_enum_expr = copy_list_range(defn, NULL);
218 struct string_list *expr;
221 snprintf(buf, sizeof(buf), "%d", enum_counter++);
222 if (last_enum_expr) {
223 expr = copy_list_range(last_enum_expr, NULL);
224 defn = concat_list(mk_node("("),
233 } else if (type == SYM_ENUM) {
234 free_list(last_enum_expr, NULL);
235 last_enum_expr = NULL;
238 /* Anonymous enum definition, nothing more to do */
242 h = crc32(name) % HASH_BUCKETS;
243 for (sym = symtab[h]; sym; sym = sym->hash_next) {
244 if (map_to_ns(sym->type) == map_to_ns(type) &&
245 strcmp(name, sym->name) == 0) {
248 else if (sym->type == type &&
249 equal_list(sym->defn, defn)) {
250 if (!sym->is_declared && sym->is_override) {
252 print_type_name(type, name);
253 fprintf(stderr, " modversion is "
256 sym->is_declared = 1;
258 } else if (!sym->is_declared) {
259 if (sym->is_override && flag_preserve) {
261 fprintf(stderr, "ignoring ");
262 print_type_name(type, name);
263 fprintf(stderr, " modversion change\n");
264 sym->is_declared = 1;
267 status = is_unknown_symbol(sym) ?
268 STATUS_DEFINED : STATUS_MODIFIED;
271 error_with_pos("redefinition of %s", name);
279 struct symbol **psym;
281 for (psym = &symtab[h]; *psym; psym = &(*psym)->hash_next) {
283 *psym = sym->hash_next;
290 sym = xmalloc(sizeof(*sym));
294 sym->expansion_trail = NULL;
296 sym->is_extern = is_extern;
298 sym->hash_next = symtab[h];
301 sym->is_declared = !is_reference;
302 sym->status = status;
303 sym->is_override = 0;
306 if (symbol_types[type].name)
307 fprintf(debugfile, "Defn for %s %s == <",
308 symbol_types[type].name, name);
310 fprintf(debugfile, "Defn for type%d %s == <",
313 fputs("extern ", debugfile);
314 print_list(debugfile, defn);
315 fputs(">\n", debugfile);
322 struct symbol *add_symbol(const char *name, enum symbol_type type,
323 struct string_list *defn, int is_extern)
325 return __add_symbol(name, type, defn, is_extern, 0);
328 static struct symbol *add_reference_symbol(const char *name, enum symbol_type type,
329 struct string_list *defn, int is_extern)
331 return __add_symbol(name, type, defn, is_extern, 1);
334 /*----------------------------------------------------------------------*/
336 void free_node(struct string_list *node)
342 void free_list(struct string_list *s, struct string_list *e)
345 struct string_list *next = s->next;
351 static struct string_list *mk_node(const char *string)
353 struct string_list *newnode;
355 newnode = xmalloc(sizeof(*newnode));
356 newnode->string = xstrdup(string);
357 newnode->tag = SYM_NORMAL;
358 newnode->next = NULL;
363 static struct string_list *concat_list(struct string_list *start, ...)
366 struct string_list *n, *n2;
370 for (va_start(ap, start); (n = va_arg(ap, struct string_list *));) {
371 for (n2 = n; n2->next; n2 = n2->next)
380 struct string_list *copy_node(struct string_list *node)
382 struct string_list *newnode;
384 newnode = xmalloc(sizeof(*newnode));
385 newnode->string = xstrdup(node->string);
386 newnode->tag = node->tag;
391 struct string_list *copy_list_range(struct string_list *start,
392 struct string_list *end)
394 struct string_list *res, *n;
398 n = res = copy_node(start);
399 for (start = start->next; start != end; start = start->next) {
400 n->next = copy_node(start);
407 static int equal_list(struct string_list *a, struct string_list *b)
410 if (a->tag != b->tag || strcmp(a->string, b->string))
419 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
421 static struct string_list *read_node(FILE *f)
424 struct string_list node = {
429 while ((c = fgetc(f)) != EOF) {
431 if (node.string == buffer)
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("%s__crc_%s = 0x%08lx ;\n", mod_prefix, name, crc);
699 /*----------------------------------------------------------------------*/
701 static void print_location(void)
703 fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line);
706 static void print_type_name(enum symbol_type type, const char *name)
708 if (symbol_types[type].name)
709 fprintf(stderr, "%s %s", symbol_types[type].name, name);
711 fprintf(stderr, "%s", name);
714 void error_with_pos(const char *fmt, ...)
722 vfprintf(stderr, fmt, args);
730 static void genksyms_usage(void)
732 fputs("Usage:\n" "genksyms [-adDTwqhV] > /path/to/.tmp_obj.ver\n" "\n"
733 #ifdef __GNU_LIBRARY__
734 " -a, --arch Select architecture\n"
735 " -d, --debug Increment the debug level (repeatable)\n"
736 " -D, --dump Dump expanded symbol defs (for debugging only)\n"
737 " -r, --reference file Read reference symbols from a file\n"
738 " -T, --dump-types file Dump expanded types into file\n"
739 " -p, --preserve Preserve reference modversions or fail\n"
740 " -w, --warnings Enable warnings\n"
741 " -q, --quiet Disable warnings (default)\n"
742 " -h, --help Print this message\n"
743 " -V, --version Print the release version\n"
744 #else /* __GNU_LIBRARY__ */
745 " -a Select architecture\n"
746 " -d Increment the debug level (repeatable)\n"
747 " -D Dump expanded symbol defs (for debugging only)\n"
748 " -r file Read reference symbols from a file\n"
749 " -T file Dump expanded types into file\n"
750 " -p Preserve reference modversions or fail\n"
751 " -w Enable warnings\n"
752 " -q Disable warnings (default)\n"
753 " -h Print this message\n"
754 " -V Print the release version\n"
755 #endif /* __GNU_LIBRARY__ */
759 int main(int argc, char **argv)
761 FILE *dumpfile = NULL, *ref_file = NULL;
764 #ifdef __GNU_LIBRARY__
765 struct option long_opts[] = {
767 {"debug", 0, 0, 'd'},
768 {"warnings", 0, 0, 'w'},
769 {"quiet", 0, 0, 'q'},
771 {"reference", 1, 0, 'r'},
772 {"dump-types", 1, 0, 'T'},
773 {"preserve", 0, 0, 'p'},
774 {"version", 0, 0, 'V'},
779 while ((o = getopt_long(argc, argv, "a:dwqVDr:T:ph",
780 &long_opts[0], NULL)) != EOF)
781 #else /* __GNU_LIBRARY__ */
782 while ((o = getopt(argc, argv, "a:dwqVDr:T:ph")) != EOF)
783 #endif /* __GNU_LIBRARY__ */
798 fputs("genksyms version 2.5.60\n", stderr);
805 ref_file = fopen(optarg, "r");
813 dumpfile = fopen(optarg, "w");
829 if ((strcmp(arch, "h8300") == 0) || (strcmp(arch, "blackfin") == 0) ||
830 (strcmp(arch, "metag") == 0))
834 extern int yy_flex_debug;
836 yydebug = (flag_debug > 1);
837 yy_flex_debug = (flag_debug > 2);
840 /* setlinebuf(debugfile); */
843 if (flag_reference) {
844 read_reference(ref_file);
850 if (flag_dump_types && visited_symbols) {
851 while (visited_symbols != (struct symbol *)-1L) {
852 struct symbol *sym = visited_symbols;
854 if (sym->is_override)
855 fputs("override ", dumpfile);
856 if (symbol_types[sym->type].n) {
857 putc(symbol_types[sym->type].n, dumpfile);
860 fputs(sym->name, dumpfile);
863 fputs("extern ", dumpfile);
864 print_list(dumpfile, sym->defn);
865 putc('\n', dumpfile);
867 visited_symbols = sym->visited;
873 fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
875 (double)nsyms / (double)HASH_BUCKETS);