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__ */
36 /*----------------------------------------------------------------------*/
38 #define HASH_BUCKETS 4096
40 static struct symbol *symtab[HASH_BUCKETS];
44 char *cur_filename, *output_directory;
46 int flag_debug, flag_dump_defs, flag_warnings;
51 static struct symbol *expansion_trail;
53 static const char * const symbol_type_name[] = {
54 "normal", "typedef", "enum", "struct", "union"
57 /*----------------------------------------------------------------------*/
59 static const unsigned int crctab32[] =
61 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U,
62 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U,
63 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U,
64 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU,
65 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U,
66 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U,
67 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U,
68 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU,
69 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U,
70 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU,
71 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U,
72 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
73 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U,
74 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU,
75 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU,
76 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U,
77 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU,
78 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U,
79 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U,
80 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U,
81 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU,
82 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U,
83 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U,
84 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
85 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U,
86 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U,
87 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U,
88 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
89 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U,
90 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU,
91 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU,
92 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U,
93 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U,
94 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU,
95 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU,
96 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
97 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU,
98 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U,
99 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU,
100 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U,
101 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU,
102 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
103 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U,
104 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU,
105 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U,
106 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U,
107 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U,
108 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
109 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U,
110 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U,
111 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU,
115 static inline unsigned long
116 partial_crc32_one(unsigned char c, unsigned long crc)
118 return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
121 static inline unsigned long
122 partial_crc32(const char *s, unsigned long crc)
125 crc = partial_crc32_one(*s++, crc);
129 static inline unsigned long
132 return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
136 /*----------------------------------------------------------------------*/
138 static inline enum symbol_type
139 map_to_ns(enum symbol_type t)
141 if (t == SYM_TYPEDEF)
143 else if (t == SYM_UNION)
149 find_symbol(const char *name, enum symbol_type ns)
151 unsigned long h = crc32(name) % HASH_BUCKETS;
154 for (sym = symtab[h]; sym ; sym = sym->hash_next)
155 if (map_to_ns(sym->type) == map_to_ns(ns) && strcmp(name, sym->name) == 0)
162 add_symbol(const char *name, enum symbol_type type, struct string_list *defn, int is_extern)
164 unsigned long h = crc32(name) % HASH_BUCKETS;
167 for (sym = symtab[h]; sym ; sym = sym->hash_next)
168 if (map_to_ns(sym->type) == map_to_ns(type)
169 && strcmp(name, sym->name) == 0)
171 if (!equal_list(sym->defn, defn))
172 error_with_pos("redefinition of %s", name);
176 sym = xmalloc(sizeof(*sym));
180 sym->expansion_trail = NULL;
181 sym->is_extern = is_extern;
183 sym->hash_next = symtab[h];
188 fprintf(debugfile, "Defn for %s %s == <", symbol_type_name[type], name);
190 fputs("extern ", debugfile);
191 print_list(debugfile, defn);
192 fputs(">\n", debugfile);
200 /*----------------------------------------------------------------------*/
203 free_node(struct string_list *node)
210 free_list(struct string_list *s, struct string_list *e)
214 struct string_list *next = s->next;
220 inline struct string_list *
221 copy_node(struct string_list *node)
223 struct string_list *newnode;
225 newnode = xmalloc(sizeof(*newnode));
226 newnode->string = xstrdup(node->string);
227 newnode->tag = node->tag;
233 copy_list(struct string_list *s, struct string_list *e)
235 struct string_list *h, *p;
240 p = h = copy_node(s);
241 while ((s = s->next) != e)
242 p = p->next = copy_node(s);
249 equal_list(struct string_list *a, struct string_list *b)
253 if (a->tag != b->tag || strcmp(a->string, b->string))
263 print_node(FILE *f, struct string_list *list)
283 fputs(list->string, f);
289 print_list(FILE *f, struct string_list *list)
291 struct string_list **e, **b;
292 struct string_list *tmp, **tmp2;
302 while((tmp = tmp->next) != NULL)
305 b = alloca(elem * sizeof(*e));
310 while((list = list->next) != NULL)
321 expand_and_crc_list(struct string_list *list, unsigned long crc)
323 struct string_list **e, **b;
324 struct string_list *tmp, **tmp2;
331 while((tmp = tmp->next) != NULL)
334 b = alloca(elem * sizeof(*e));
339 while ((list = list->next) != NULL)
344 struct string_list *cur;
345 struct symbol *subsym;
352 fprintf(debugfile, "%s ", cur->string);
353 crc = partial_crc32(cur->string, crc);
354 crc = partial_crc32_one(' ', crc);
358 subsym = find_symbol(cur->string, cur->tag);
359 if (subsym->expansion_trail)
362 fprintf(debugfile, "%s ", cur->string);
363 crc = partial_crc32(cur->string, crc);
364 crc = partial_crc32_one(' ', crc);
368 subsym->expansion_trail = expansion_trail;
369 expansion_trail = subsym;
370 crc = expand_and_crc_list(subsym->defn, crc);
377 subsym = find_symbol(cur->string, cur->tag);
380 struct string_list *n, *t = NULL;
382 error_with_pos("expand undefined %s %s",
383 symbol_type_name[cur->tag], cur->string);
385 n = xmalloc(sizeof(*n));
386 n->string = xstrdup(symbol_type_name[cur->tag]);
391 n = xmalloc(sizeof(*n));
392 n->string = xstrdup(cur->string);
397 n = xmalloc(sizeof(*n));
398 n->string = xstrdup("{ UNKNOWN }");
402 subsym = add_symbol(cur->string, cur->tag, n, 0);
404 if (subsym->expansion_trail)
408 fprintf(debugfile, "%s %s ", symbol_type_name[cur->tag],
412 crc = partial_crc32(symbol_type_name[cur->tag], crc);
413 crc = partial_crc32_one(' ', crc);
414 crc = partial_crc32(cur->string, crc);
415 crc = partial_crc32_one(' ', crc);
419 subsym->expansion_trail = expansion_trail;
420 expansion_trail = subsym;
421 crc = expand_and_crc_list(subsym->defn, crc);
431 export_symbol(const char *name)
435 sym = find_symbol(name, SYM_NORMAL);
437 error_with_pos("export undefined symbol %s", name);
443 fprintf(debugfile, "Export %s == <", name);
445 expansion_trail = (struct symbol *)-1L;
447 crc = expand_and_crc_list(sym->defn, 0xffffffff) ^ 0xffffffff;
449 sym = expansion_trail;
450 while (sym != (struct symbol *)-1L)
452 struct symbol *n = sym->expansion_trail;
453 sym->expansion_trail = 0;
458 fputs(">\n", debugfile);
460 /* Used as a linker script. */
461 printf("__crc_%s = 0x%08lx ;\n", name, crc);
465 /*----------------------------------------------------------------------*/
468 error(const char *fmt, ...)
475 vfprintf(stderr, fmt, args);
484 error_with_pos(const char *fmt, ...)
490 fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line);
493 vfprintf(stderr, fmt, args);
502 void genksyms_usage(void)
505 "genksyms [-dDwqhV] > /path/to/.tmp_obj.ver\n"
507 #ifdef __GNU_LIBRARY__
508 " -d, --debug Increment the debug level (repeatable)\n"
509 " -D, --dump Dump expanded symbol defs (for debugging only)\n"
510 " -w, --warnings Enable warnings\n"
511 " -q, --quiet Disable warnings (default)\n"
512 " -h, --help Print this message\n"
513 " -V, --version Print the release version\n"
514 #else /* __GNU_LIBRARY__ */
515 " -d Increment the debug level (repeatable)\n"
516 " -D Dump expanded symbol defs (for debugging only)\n"
517 " -w Enable warnings\n"
518 " -q Disable warnings (default)\n"
519 " -h Print this message\n"
520 " -V Print the release version\n"
521 #endif /* __GNU_LIBRARY__ */
526 main(int argc, char **argv)
530 #ifdef __GNU_LIBRARY__
531 struct option long_opts[] = {
532 {"debug", 0, 0, 'd'},
533 {"warnings", 0, 0, 'w'},
534 {"quiet", 0, 0, 'q'},
536 {"version", 0, 0, 'V'},
541 while ((o = getopt_long(argc, argv, "dwqVDk:p:",
542 &long_opts[0], NULL)) != EOF)
543 #else /* __GNU_LIBRARY__ */
544 while ((o = getopt(argc, argv, "dwqVDk:p:")) != EOF)
545 #endif /* __GNU_LIBRARY__ */
558 fputs("genksyms version 2.5.60\n", stderr);
573 extern int yy_flex_debug;
575 yydebug = (flag_debug > 1);
576 yy_flex_debug = (flag_debug > 2);
579 /* setlinebuf(debugfile); */
586 fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
587 nsyms, HASH_BUCKETS, (double)nsyms / (double)HASH_BUCKETS);