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];
43 char *cur_filename, *output_directory;
45 int flag_debug, flag_dump_defs, flag_warnings;
46 const char *arch = "";
47 const char *mod_prefix = "";
52 static struct symbol *expansion_trail;
54 static const char *const symbol_type_name[] = {
55 "normal", "typedef", "enum", "struct", "union"
58 /*----------------------------------------------------------------------*/
60 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 partial_crc32(const char *s, unsigned long crc)
124 crc = partial_crc32_one(*s++, crc);
128 static inline unsigned long crc32(const char *s)
130 return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
133 /*----------------------------------------------------------------------*/
135 static inline enum symbol_type map_to_ns(enum symbol_type t)
137 if (t == SYM_TYPEDEF)
139 else if (t == SYM_UNION)
144 struct symbol *find_symbol(const char *name, enum symbol_type ns)
146 unsigned long h = crc32(name) % HASH_BUCKETS;
149 for (sym = symtab[h]; sym; sym = sym->hash_next)
150 if (map_to_ns(sym->type) == map_to_ns(ns)
151 && strcmp(name, sym->name) == 0)
157 struct symbol *add_symbol(const char *name, enum symbol_type type,
158 struct string_list *defn, int is_extern)
160 unsigned long h = crc32(name) % HASH_BUCKETS;
163 for (sym = symtab[h]; sym; sym = sym->hash_next)
164 if (map_to_ns(sym->type) == map_to_ns(type)
165 && strcmp(name, sym->name) == 0) {
166 if (!equal_list(sym->defn, defn))
167 error_with_pos("redefinition of %s", name);
171 sym = xmalloc(sizeof(*sym));
175 sym->expansion_trail = NULL;
176 sym->is_extern = is_extern;
178 sym->hash_next = symtab[h];
182 fprintf(debugfile, "Defn for %s %s == <",
183 symbol_type_name[type], name);
185 fputs("extern ", debugfile);
186 print_list(debugfile, defn);
187 fputs(">\n", debugfile);
194 /*----------------------------------------------------------------------*/
196 inline void free_node(struct string_list *node)
202 void free_list(struct string_list *s, struct string_list *e)
205 struct string_list *next = s->next;
211 inline struct string_list *copy_node(struct string_list *node)
213 struct string_list *newnode;
215 newnode = xmalloc(sizeof(*newnode));
216 newnode->string = xstrdup(node->string);
217 newnode->tag = node->tag;
222 struct string_list *copy_list(struct string_list *s, struct string_list *e)
224 struct string_list *h, *p;
229 p = h = copy_node(s);
230 while ((s = s->next) != e)
231 p = p->next = copy_node(s);
237 int equal_list(struct string_list *a, struct string_list *b)
240 if (a->tag != b->tag || strcmp(a->string, b->string))
249 static inline void print_node(FILE * f, struct string_list *list)
268 fputs(list->string, f);
273 void print_list(FILE * f, struct string_list *list)
275 struct string_list **e, **b;
276 struct string_list *tmp, **tmp2;
285 while ((tmp = tmp->next) != NULL)
288 b = alloca(elem * sizeof(*e));
293 while ((list = list->next) != NULL)
303 expand_and_crc_list(struct string_list *list, unsigned long crc)
305 struct string_list **e, **b;
306 struct string_list *tmp, **tmp2;
313 while ((tmp = tmp->next) != NULL)
316 b = alloca(elem * sizeof(*e));
321 while ((list = list->next) != NULL)
325 struct string_list *cur;
326 struct symbol *subsym;
332 fprintf(debugfile, "%s ", cur->string);
333 crc = partial_crc32(cur->string, crc);
334 crc = partial_crc32_one(' ', crc);
338 subsym = find_symbol(cur->string, cur->tag);
339 if (subsym->expansion_trail) {
341 fprintf(debugfile, "%s ", cur->string);
342 crc = partial_crc32(cur->string, crc);
343 crc = partial_crc32_one(' ', crc);
345 subsym->expansion_trail = expansion_trail;
346 expansion_trail = subsym;
347 crc = expand_and_crc_list(subsym->defn, crc);
354 subsym = find_symbol(cur->string, cur->tag);
356 struct string_list *n, *t = NULL;
358 error_with_pos("expand undefined %s %s",
359 symbol_type_name[cur->tag],
362 n = xmalloc(sizeof(*n));
363 n->string = xstrdup(symbol_type_name[cur->tag]);
368 n = xmalloc(sizeof(*n));
369 n->string = xstrdup(cur->string);
374 n = xmalloc(sizeof(*n));
375 n->string = xstrdup("{ UNKNOWN }");
380 add_symbol(cur->string, cur->tag, n, 0);
382 if (subsym->expansion_trail) {
383 if (flag_dump_defs) {
384 fprintf(debugfile, "%s %s ",
385 symbol_type_name[cur->tag],
390 partial_crc32(symbol_type_name[cur->tag],
392 crc = partial_crc32_one(' ', crc);
393 crc = partial_crc32(cur->string, crc);
394 crc = partial_crc32_one(' ', crc);
396 subsym->expansion_trail = expansion_trail;
397 expansion_trail = subsym;
398 crc = expand_and_crc_list(subsym->defn, crc);
407 void export_symbol(const char *name)
411 sym = find_symbol(name, SYM_NORMAL);
413 error_with_pos("export undefined symbol %s", name);
418 fprintf(debugfile, "Export %s == <", name);
420 expansion_trail = (struct symbol *)-1L;
422 crc = expand_and_crc_list(sym->defn, 0xffffffff) ^ 0xffffffff;
424 sym = expansion_trail;
425 while (sym != (struct symbol *)-1L) {
426 struct symbol *n = sym->expansion_trail;
427 sym->expansion_trail = 0;
432 fputs(">\n", debugfile);
434 /* Used as a linker script. */
435 printf("%s__crc_%s = 0x%08lx ;\n", mod_prefix, name, crc);
439 /*----------------------------------------------------------------------*/
441 void error(const char *fmt, ...)
447 vfprintf(stderr, fmt, args);
455 void error_with_pos(const char *fmt, ...)
460 fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>",
464 vfprintf(stderr, fmt, args);
472 void genksyms_usage(void)
474 fputs("Usage:\n" "genksyms [-dDwqhV] > /path/to/.tmp_obj.ver\n" "\n"
475 #ifdef __GNU_LIBRARY__
476 " -d, --debug Increment the debug level (repeatable)\n"
477 " -D, --dump Dump expanded symbol defs (for debugging only)\n"
478 " -w, --warnings Enable warnings\n"
479 " -q, --quiet Disable warnings (default)\n"
480 " -h, --help Print this message\n"
481 " -V, --version Print the release version\n"
482 #else /* __GNU_LIBRARY__ */
483 " -d Increment the debug level (repeatable)\n"
484 " -D Dump expanded symbol defs (for debugging only)\n"
485 " -w Enable warnings\n"
486 " -q Disable warnings (default)\n"
487 " -h Print this message\n"
488 " -V Print the release version\n"
489 #endif /* __GNU_LIBRARY__ */
493 int main(int argc, char **argv)
497 #ifdef __GNU_LIBRARY__
498 struct option long_opts[] = {
500 {"debug", 0, 0, 'd'},
501 {"warnings", 0, 0, 'w'},
502 {"quiet", 0, 0, 'q'},
504 {"version", 0, 0, 'V'},
509 while ((o = getopt_long(argc, argv, "a:dwqVDk:p:",
510 &long_opts[0], NULL)) != EOF)
511 #else /* __GNU_LIBRARY__ */
512 while ((o = getopt(argc, argv, "a:dwqVDk:p:")) != EOF)
513 #endif /* __GNU_LIBRARY__ */
528 fputs("genksyms version 2.5.60\n", stderr);
540 if ((strcmp(arch, "v850") == 0) || (strcmp(arch, "h8300") == 0))
544 extern int yy_flex_debug;
546 yydebug = (flag_debug > 1);
547 yy_flex_debug = (flag_debug > 2);
550 /* setlinebuf(debugfile); */
556 fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
558 (double)nsyms / (double)HASH_BUCKETS);