]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - scripts/genksyms/genksyms.c
Linux-2.6.12-rc2
[mirror_ubuntu-bionic-kernel.git] / scripts / genksyms / genksyms.c
1 /* Generate kernel symbol version hashes.
2 Copyright 1996, 1997 Linux International.
3
4 New implementation contributed by Richard Henderson <rth@tamu.edu>
5 Based on original work by Bjorn Ekwall <bj0rn@blox.se>
6
7 This file was part of the Linux modutils 2.4.22: moved back into the
8 kernel sources by Rusty Russell/Kai Germaschewski.
9
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.
14
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.
19
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. */
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <assert.h>
29 #include <stdarg.h>
30 #ifdef __GNU_LIBRARY__
31 #include <getopt.h>
32 #endif /* __GNU_LIBRARY__ */
33
34 #include "genksyms.h"
35
36 /*----------------------------------------------------------------------*/
37
38 #define HASH_BUCKETS 4096
39
40 static struct symbol *symtab[HASH_BUCKETS];
41 FILE *debugfile;
42
43 int cur_line = 1;
44 char *cur_filename, *output_directory;
45
46 int flag_debug, flag_dump_defs, flag_warnings;
47
48 static int errors;
49 static int nsyms;
50
51 static struct symbol *expansion_trail;
52
53 static const char * const symbol_type_name[] = {
54 "normal", "typedef", "enum", "struct", "union"
55 };
56
57 /*----------------------------------------------------------------------*/
58
59 static const unsigned int crctab32[] =
60 {
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,
112 0x2d02ef8dU
113 };
114
115 static inline unsigned long
116 partial_crc32_one(unsigned char c, unsigned long crc)
117 {
118 return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
119 }
120
121 static inline unsigned long
122 partial_crc32(const char *s, unsigned long crc)
123 {
124 while (*s)
125 crc = partial_crc32_one(*s++, crc);
126 return crc;
127 }
128
129 static inline unsigned long
130 crc32(const char *s)
131 {
132 return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
133 }
134
135
136 /*----------------------------------------------------------------------*/
137
138 static inline enum symbol_type
139 map_to_ns(enum symbol_type t)
140 {
141 if (t == SYM_TYPEDEF)
142 t = SYM_NORMAL;
143 else if (t == SYM_UNION)
144 t = SYM_STRUCT;
145 return t;
146 }
147
148 struct symbol *
149 find_symbol(const char *name, enum symbol_type ns)
150 {
151 unsigned long h = crc32(name) % HASH_BUCKETS;
152 struct symbol *sym;
153
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)
156 break;
157
158 return sym;
159 }
160
161 struct symbol *
162 add_symbol(const char *name, enum symbol_type type, struct string_list *defn, int is_extern)
163 {
164 unsigned long h = crc32(name) % HASH_BUCKETS;
165 struct symbol *sym;
166
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)
170 {
171 if (!equal_list(sym->defn, defn))
172 error_with_pos("redefinition of %s", name);
173 return sym;
174 }
175
176 sym = xmalloc(sizeof(*sym));
177 sym->name = name;
178 sym->type = type;
179 sym->defn = defn;
180 sym->expansion_trail = NULL;
181 sym->is_extern = is_extern;
182
183 sym->hash_next = symtab[h];
184 symtab[h] = sym;
185
186 if (flag_debug)
187 {
188 fprintf(debugfile, "Defn for %s %s == <", symbol_type_name[type], name);
189 if (is_extern)
190 fputs("extern ", debugfile);
191 print_list(debugfile, defn);
192 fputs(">\n", debugfile);
193 }
194
195 ++nsyms;
196 return sym;
197 }
198
199
200 /*----------------------------------------------------------------------*/
201
202 inline void
203 free_node(struct string_list *node)
204 {
205 free(node->string);
206 free(node);
207 }
208
209 void
210 free_list(struct string_list *s, struct string_list *e)
211 {
212 while (s != e)
213 {
214 struct string_list *next = s->next;
215 free_node(s);
216 s = next;
217 }
218 }
219
220 inline struct string_list *
221 copy_node(struct string_list *node)
222 {
223 struct string_list *newnode;
224
225 newnode = xmalloc(sizeof(*newnode));
226 newnode->string = xstrdup(node->string);
227 newnode->tag = node->tag;
228
229 return newnode;
230 }
231
232 struct string_list *
233 copy_list(struct string_list *s, struct string_list *e)
234 {
235 struct string_list *h, *p;
236
237 if (s == e)
238 return NULL;
239
240 p = h = copy_node(s);
241 while ((s = s->next) != e)
242 p = p->next = copy_node(s);
243 p->next = NULL;
244
245 return h;
246 }
247
248 int
249 equal_list(struct string_list *a, struct string_list *b)
250 {
251 while (a && b)
252 {
253 if (a->tag != b->tag || strcmp(a->string, b->string))
254 return 0;
255 a = a->next;
256 b = b->next;
257 }
258
259 return !a && !b;
260 }
261
262 static inline void
263 print_node(FILE *f, struct string_list *list)
264 {
265 switch (list->tag)
266 {
267 case SYM_STRUCT:
268 putc('s', f);
269 goto printit;
270 case SYM_UNION:
271 putc('u', f);
272 goto printit;
273 case SYM_ENUM:
274 putc('e', f);
275 goto printit;
276 case SYM_TYPEDEF:
277 putc('t', f);
278 goto printit;
279
280 printit:
281 putc('#', f);
282 case SYM_NORMAL:
283 fputs(list->string, f);
284 break;
285 }
286 }
287
288 void
289 print_list(FILE *f, struct string_list *list)
290 {
291 struct string_list **e, **b;
292 struct string_list *tmp, **tmp2;
293 int elem = 1;
294
295 if (list == NULL)
296 {
297 fputs("(nil)", f);
298 return;
299 }
300
301 tmp = list;
302 while((tmp = tmp->next) != NULL)
303 elem++;
304
305 b = alloca(elem * sizeof(*e));
306 e = b + elem;
307 tmp2 = e - 1;
308
309 (*tmp2--) = list;
310 while((list = list->next) != NULL)
311 *(tmp2--) = list;
312
313 while (b != e)
314 {
315 print_node(f, *b++);
316 putc(' ', f);
317 }
318 }
319
320 static unsigned long
321 expand_and_crc_list(struct string_list *list, unsigned long crc)
322 {
323 struct string_list **e, **b;
324 struct string_list *tmp, **tmp2;
325 int elem = 1;
326
327 if (!list)
328 return crc;
329
330 tmp = list;
331 while((tmp = tmp->next) != NULL)
332 elem++;
333
334 b = alloca(elem * sizeof(*e));
335 e = b + elem;
336 tmp2 = e - 1;
337
338 *(tmp2--) = list;
339 while ((list = list->next) != NULL)
340 *(tmp2--) = list;
341
342 while (b != e)
343 {
344 struct string_list *cur;
345 struct symbol *subsym;
346
347 cur = *(b++);
348 switch (cur->tag)
349 {
350 case SYM_NORMAL:
351 if (flag_dump_defs)
352 fprintf(debugfile, "%s ", cur->string);
353 crc = partial_crc32(cur->string, crc);
354 crc = partial_crc32_one(' ', crc);
355 break;
356
357 case SYM_TYPEDEF:
358 subsym = find_symbol(cur->string, cur->tag);
359 if (subsym->expansion_trail)
360 {
361 if (flag_dump_defs)
362 fprintf(debugfile, "%s ", cur->string);
363 crc = partial_crc32(cur->string, crc);
364 crc = partial_crc32_one(' ', crc);
365 }
366 else
367 {
368 subsym->expansion_trail = expansion_trail;
369 expansion_trail = subsym;
370 crc = expand_and_crc_list(subsym->defn, crc);
371 }
372 break;
373
374 case SYM_STRUCT:
375 case SYM_UNION:
376 case SYM_ENUM:
377 subsym = find_symbol(cur->string, cur->tag);
378 if (!subsym)
379 {
380 struct string_list *n, *t = NULL;
381
382 error_with_pos("expand undefined %s %s",
383 symbol_type_name[cur->tag], cur->string);
384
385 n = xmalloc(sizeof(*n));
386 n->string = xstrdup(symbol_type_name[cur->tag]);
387 n->tag = SYM_NORMAL;
388 n->next = t;
389 t = n;
390
391 n = xmalloc(sizeof(*n));
392 n->string = xstrdup(cur->string);
393 n->tag = SYM_NORMAL;
394 n->next = t;
395 t = n;
396
397 n = xmalloc(sizeof(*n));
398 n->string = xstrdup("{ UNKNOWN }");
399 n->tag = SYM_NORMAL;
400 n->next = t;
401
402 subsym = add_symbol(cur->string, cur->tag, n, 0);
403 }
404 if (subsym->expansion_trail)
405 {
406 if (flag_dump_defs)
407 {
408 fprintf(debugfile, "%s %s ", symbol_type_name[cur->tag],
409 cur->string);
410 }
411
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);
416 }
417 else
418 {
419 subsym->expansion_trail = expansion_trail;
420 expansion_trail = subsym;
421 crc = expand_and_crc_list(subsym->defn, crc);
422 }
423 break;
424 }
425 }
426
427 return crc;
428 }
429
430 void
431 export_symbol(const char *name)
432 {
433 struct symbol *sym;
434
435 sym = find_symbol(name, SYM_NORMAL);
436 if (!sym)
437 error_with_pos("export undefined symbol %s", name);
438 else
439 {
440 unsigned long crc;
441
442 if (flag_dump_defs)
443 fprintf(debugfile, "Export %s == <", name);
444
445 expansion_trail = (struct symbol *)-1L;
446
447 crc = expand_and_crc_list(sym->defn, 0xffffffff) ^ 0xffffffff;
448
449 sym = expansion_trail;
450 while (sym != (struct symbol *)-1L)
451 {
452 struct symbol *n = sym->expansion_trail;
453 sym->expansion_trail = 0;
454 sym = n;
455 }
456
457 if (flag_dump_defs)
458 fputs(">\n", debugfile);
459
460 /* Used as a linker script. */
461 printf("__crc_%s = 0x%08lx ;\n", name, crc);
462 }
463 }
464
465 /*----------------------------------------------------------------------*/
466
467 void
468 error(const char *fmt, ...)
469 {
470 va_list args;
471
472 if (flag_warnings)
473 {
474 va_start(args, fmt);
475 vfprintf(stderr, fmt, args);
476 va_end(args);
477 putc('\n', stderr);
478
479 errors++;
480 }
481 }
482
483 void
484 error_with_pos(const char *fmt, ...)
485 {
486 va_list args;
487
488 if (flag_warnings)
489 {
490 fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line);
491
492 va_start(args, fmt);
493 vfprintf(stderr, fmt, args);
494 va_end(args);
495 putc('\n', stderr);
496
497 errors++;
498 }
499 }
500
501
502 void genksyms_usage(void)
503 {
504 fputs("Usage:\n"
505 "genksyms [-dDwqhV] > /path/to/.tmp_obj.ver\n"
506 "\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__ */
522 , stderr);
523 }
524
525 int
526 main(int argc, char **argv)
527 {
528 int o;
529
530 #ifdef __GNU_LIBRARY__
531 struct option long_opts[] = {
532 {"debug", 0, 0, 'd'},
533 {"warnings", 0, 0, 'w'},
534 {"quiet", 0, 0, 'q'},
535 {"dump", 0, 0, 'D'},
536 {"version", 0, 0, 'V'},
537 {"help", 0, 0, 'h'},
538 {0, 0, 0, 0}
539 };
540
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__ */
546 switch (o)
547 {
548 case 'd':
549 flag_debug++;
550 break;
551 case 'w':
552 flag_warnings = 1;
553 break;
554 case 'q':
555 flag_warnings = 0;
556 break;
557 case 'V':
558 fputs("genksyms version 2.5.60\n", stderr);
559 break;
560 case 'D':
561 flag_dump_defs = 1;
562 break;
563 case 'h':
564 genksyms_usage();
565 return 0;
566 default:
567 genksyms_usage();
568 return 1;
569 }
570
571 {
572 extern int yydebug;
573 extern int yy_flex_debug;
574
575 yydebug = (flag_debug > 1);
576 yy_flex_debug = (flag_debug > 2);
577
578 debugfile = stderr;
579 /* setlinebuf(debugfile); */
580 }
581
582 yyparse();
583
584 if (flag_debug)
585 {
586 fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
587 nsyms, HASH_BUCKETS, (double)nsyms / (double)HASH_BUCKETS);
588 }
589
590 return errors != 0;
591 }