1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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
33
34#include "genksyms.h"
35
36
37#define HASH_BUCKETS 4096
38
39static struct symbol *symtab[HASH_BUCKETS];
40static FILE *debugfile;
41
42int cur_line = 1;
43char *cur_filename;
44
45static int flag_debug, flag_dump_defs, flag_dump_types, flag_warnings;
46static const char *arch = "";
47static const char *mod_prefix = "";
48
49static int errors;
50static int nsyms;
51
52static struct symbol *expansion_trail;
53static struct symbol *visited_symbols;
54
55static const char *const symbol_type_name[] = {
56 "normal", "typedef", "enum", "struct", "union"
57};
58
59static int equal_list(struct string_list *a, struct string_list *b);
60static void print_list(FILE * f, struct string_list *list);
61
62
63
64static const unsigned int crctab32[] = {
65 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U,
66 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U,
67 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U,
68 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU,
69 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U,
70 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U,
71 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U,
72 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU,
73 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U,
74 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU,
75 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U,
76 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
77 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U,
78 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU,
79 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU,
80 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U,
81 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU,
82 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U,
83 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U,
84 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U,
85 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU,
86 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U,
87 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U,
88 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
89 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U,
90 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U,
91 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U,
92 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
93 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U,
94 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU,
95 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU,
96 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U,
97 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U,
98 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU,
99 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU,
100 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
101 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU,
102 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U,
103 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU,
104 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U,
105 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU,
106 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
107 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U,
108 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU,
109 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U,
110 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U,
111 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U,
112 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
113 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U,
114 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U,
115 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU,
116 0x2d02ef8dU
117};
118
119static unsigned long partial_crc32_one(unsigned char c, unsigned long crc)
120{
121 return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
122}
123
124static unsigned long partial_crc32(const char *s, unsigned long crc)
125{
126 while (*s)
127 crc = partial_crc32_one(*s++, crc);
128 return crc;
129}
130
131static unsigned long crc32(const char *s)
132{
133 return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
134}
135
136
137
138static enum symbol_type map_to_ns(enum symbol_type t)
139{
140 if (t == SYM_TYPEDEF)
141 t = SYM_NORMAL;
142 else if (t == SYM_UNION)
143 t = SYM_STRUCT;
144 return t;
145}
146
147struct symbol *find_symbol(const char *name, enum symbol_type ns)
148{
149 unsigned long h = crc32(name) % HASH_BUCKETS;
150 struct symbol *sym;
151
152 for (sym = symtab[h]; sym; sym = sym->hash_next)
153 if (map_to_ns(sym->type) == map_to_ns(ns) &&
154 strcmp(name, sym->name) == 0)
155 break;
156
157 return sym;
158}
159
160struct symbol *add_symbol(const char *name, enum symbol_type type,
161 struct string_list *defn, int is_extern)
162{
163 unsigned long h = crc32(name) % HASH_BUCKETS;
164 struct symbol *sym;
165
166 for (sym = symtab[h]; sym; sym = sym->hash_next) {
167 if (map_to_ns(sym->type) == map_to_ns(type)
168 && strcmp(name, sym->name) == 0) {
169 if (!equal_list(sym->defn, defn))
170 error_with_pos("redefinition of %s", name);
171 return sym;
172 }
173 }
174
175 sym = xmalloc(sizeof(*sym));
176 sym->name = name;
177 sym->type = type;
178 sym->defn = defn;
179 sym->expansion_trail = NULL;
180 sym->visited = NULL;
181 sym->is_extern = is_extern;
182
183 sym->hash_next = symtab[h];
184 symtab[h] = sym;
185
186 if (flag_debug) {
187 fprintf(debugfile, "Defn for %s %s == <",
188 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
201void free_node(struct string_list *node)
202{
203 free(node->string);
204 free(node);
205}
206
207void free_list(struct string_list *s, struct string_list *e)
208{
209 while (s != e) {
210 struct string_list *next = s->next;
211 free_node(s);
212 s = next;
213 }
214}
215
216struct string_list *copy_node(struct string_list *node)
217{
218 struct string_list *newnode;
219
220 newnode = xmalloc(sizeof(*newnode));
221 newnode->string = xstrdup(node->string);
222 newnode->tag = node->tag;
223
224 return newnode;
225}
226
227static int equal_list(struct string_list *a, struct string_list *b)
228{
229 while (a && b) {
230 if (a->tag != b->tag || strcmp(a->string, b->string))
231 return 0;
232 a = a->next;
233 b = b->next;
234 }
235
236 return !a && !b;
237}
238
239static void print_node(FILE * f, struct string_list *list)
240{
241 if (list->tag != SYM_NORMAL) {
242 putc(symbol_type_name[list->tag][0], f);
243 putc('#', f);
244 }
245 fputs(list->string, f);
246}
247
248static void print_list(FILE * f, struct string_list *list)
249{
250 struct string_list **e, **b;
251 struct string_list *tmp, **tmp2;
252 int elem = 1;
253
254 if (list == NULL) {
255 fputs("(nil)", f);
256 return;
257 }
258
259 tmp = list;
260 while ((tmp = tmp->next) != NULL)
261 elem++;
262
263 b = alloca(elem * sizeof(*e));
264 e = b + elem;
265 tmp2 = e - 1;
266
267 (*tmp2--) = list;
268 while ((list = list->next) != NULL)
269 *(tmp2--) = list;
270
271 while (b != e) {
272 print_node(f, *b++);
273 putc(' ', f);
274 }
275}
276
277static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
278{
279 struct string_list *list = sym->defn;
280 struct string_list **e, **b;
281 struct string_list *tmp, **tmp2;
282 int elem = 1;
283
284 if (!list)
285 return crc;
286
287 tmp = list;
288 while ((tmp = tmp->next) != NULL)
289 elem++;
290
291 b = alloca(elem * sizeof(*e));
292 e = b + elem;
293 tmp2 = e - 1;
294
295 *(tmp2--) = list;
296 while ((list = list->next) != NULL)
297 *(tmp2--) = list;
298
299 while (b != e) {
300 struct string_list *cur;
301 struct symbol *subsym;
302
303 cur = *(b++);
304 switch (cur->tag) {
305 case SYM_NORMAL:
306 if (flag_dump_defs)
307 fprintf(debugfile, "%s ", cur->string);
308 crc = partial_crc32(cur->string, crc);
309 crc = partial_crc32_one(' ', crc);
310 break;
311
312 case SYM_TYPEDEF:
313 subsym = find_symbol(cur->string, cur->tag);
314 if (subsym->expansion_trail) {
315 if (flag_dump_defs)
316 fprintf(debugfile, "%s ", cur->string);
317 crc = partial_crc32(cur->string, crc);
318 crc = partial_crc32_one(' ', crc);
319 } else {
320 subsym->expansion_trail = expansion_trail;
321 expansion_trail = subsym;
322 crc = expand_and_crc_sym(subsym, crc);
323 }
324 break;
325
326 case SYM_STRUCT:
327 case SYM_UNION:
328 case SYM_ENUM:
329 subsym = find_symbol(cur->string, cur->tag);
330 if (!subsym) {
331 struct string_list *n, *t = NULL;
332
333 error_with_pos("expand undefined %s %s",
334 symbol_type_name[cur->tag],
335 cur->string);
336
337 n = xmalloc(sizeof(*n));
338 n->string = xstrdup(symbol_type_name[cur->tag]);
339 n->tag = SYM_NORMAL;
340 n->next = t;
341 t = n;
342
343 n = xmalloc(sizeof(*n));
344 n->string = xstrdup(cur->string);
345 n->tag = SYM_NORMAL;
346 n->next = t;
347 t = n;
348
349 n = xmalloc(sizeof(*n));
350 n->string = xstrdup("{ UNKNOWN }");
351 n->tag = SYM_NORMAL;
352 n->next = t;
353
354 subsym =
355 add_symbol(cur->string, cur->tag, n, 0);
356 }
357 if (subsym->expansion_trail) {
358 if (flag_dump_defs) {
359 fprintf(debugfile, "%s %s ",
360 symbol_type_name[cur->tag],
361 cur->string);
362 }
363
364 crc = partial_crc32(symbol_type_name[cur->tag],
365 crc);
366 crc = partial_crc32_one(' ', crc);
367 crc = partial_crc32(cur->string, crc);
368 crc = partial_crc32_one(' ', crc);
369 } else {
370 subsym->expansion_trail = expansion_trail;
371 expansion_trail = subsym;
372 crc = expand_and_crc_sym(subsym, crc);
373 }
374 break;
375 }
376 }
377
378 {
379 static struct symbol **end = &visited_symbols;
380
381 if (!sym->visited) {
382 *end = sym;
383 end = &sym->visited;
384 sym->visited = (struct symbol *)-1L;
385 }
386 }
387
388 return crc;
389}
390
391void export_symbol(const char *name)
392{
393 struct symbol *sym;
394
395 sym = find_symbol(name, SYM_NORMAL);
396 if (!sym)
397 error_with_pos("export undefined symbol %s", name);
398 else {
399 unsigned long crc;
400
401 if (flag_dump_defs)
402 fprintf(debugfile, "Export %s == <", name);
403
404 expansion_trail = (struct symbol *)-1L;
405
406 crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff;
407
408 sym = expansion_trail;
409 while (sym != (struct symbol *)-1L) {
410 struct symbol *n = sym->expansion_trail;
411 sym->expansion_trail = 0;
412 sym = n;
413 }
414
415 if (flag_dump_defs)
416 fputs(">\n", debugfile);
417
418
419 printf("%s__crc_%s = 0x%08lx ;\n", mod_prefix, name, crc);
420 }
421}
422
423
424void error_with_pos(const char *fmt, ...)
425{
426 va_list args;
427
428 if (flag_warnings) {
429 fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>",
430 cur_line);
431
432 va_start(args, fmt);
433 vfprintf(stderr, fmt, args);
434 va_end(args);
435 putc('\n', stderr);
436
437 errors++;
438 }
439}
440
441static void genksyms_usage(void)
442{
443 fputs("Usage:\n" "genksyms [-adDTwqhV] > /path/to/.tmp_obj.ver\n" "\n"
444#ifdef __GNU_LIBRARY__
445 " -a, --arch Select architecture\n"
446 " -d, --debug Increment the debug level (repeatable)\n"
447 " -D, --dump Dump expanded symbol defs (for debugging only)\n"
448 " -T, --dump-types file Dump expanded types into file (for debugging only)\n"
449 " -w, --warnings Enable warnings\n"
450 " -q, --quiet Disable warnings (default)\n"
451 " -h, --help Print this message\n"
452 " -V, --version Print the release version\n"
453#else
454 " -a Select architecture\n"
455 " -d Increment the debug level (repeatable)\n"
456 " -D Dump expanded symbol defs (for debugging only)\n"
457 " -T file Dump expanded types into file (for debugging only)\n"
458 " -w Enable warnings\n"
459 " -q Disable warnings (default)\n"
460 " -h Print this message\n"
461 " -V Print the release version\n"
462#endif
463 , stderr);
464}
465
466int main(int argc, char **argv)
467{
468 FILE *dumpfile = NULL;
469 int o;
470
471#ifdef __GNU_LIBRARY__
472 struct option long_opts[] = {
473 {"arch", 1, 0, 'a'},
474 {"debug", 0, 0, 'd'},
475 {"warnings", 0, 0, 'w'},
476 {"quiet", 0, 0, 'q'},
477 {"dump", 0, 0, 'D'},
478 {"dump-types", 1, 0, 'T'},
479 {"version", 0, 0, 'V'},
480 {"help", 0, 0, 'h'},
481 {0, 0, 0, 0}
482 };
483
484 while ((o = getopt_long(argc, argv, "a:dwqVDT:h",
485 &long_opts[0], NULL)) != EOF)
486#else
487 while ((o = getopt(argc, argv, "a:dwqVDT:h")) != EOF)
488#endif
489 switch (o) {
490 case 'a':
491 arch = optarg;
492 break;
493 case 'd':
494 flag_debug++;
495 break;
496 case 'w':
497 flag_warnings = 1;
498 break;
499 case 'q':
500 flag_warnings = 0;
501 break;
502 case 'V':
503 fputs("genksyms version 2.5.60\n", stderr);
504 break;
505 case 'D':
506 flag_dump_defs = 1;
507 break;
508 case 'T':
509 flag_dump_types = 1;
510 dumpfile = fopen(optarg, "w");
511 if (!dumpfile) {
512 perror(optarg);
513 return 1;
514 }
515 break;
516 case 'h':
517 genksyms_usage();
518 return 0;
519 default:
520 genksyms_usage();
521 return 1;
522 }
523 if ((strcmp(arch, "h8300") == 0) || (strcmp(arch, "blackfin") == 0))
524 mod_prefix = "_";
525 {
526 extern int yydebug;
527 extern int yy_flex_debug;
528
529 yydebug = (flag_debug > 1);
530 yy_flex_debug = (flag_debug > 2);
531
532 debugfile = stderr;
533
534 }
535
536 yyparse();
537
538 if (flag_dump_types && visited_symbols) {
539 while (visited_symbols != (struct symbol *)-1L) {
540 struct symbol *sym = visited_symbols;
541
542 if (sym->type != SYM_NORMAL) {
543 putc(symbol_type_name[sym->type][0], dumpfile);
544 putc('#', dumpfile);
545 }
546 fputs(sym->name, dumpfile);
547 putc(' ', dumpfile);
548 if (sym->is_extern)
549 fputs("extern ", dumpfile);
550 print_list(dumpfile, sym->defn);
551 putc('\n', dumpfile);
552
553 visited_symbols = sym->visited;
554 sym->visited = NULL;
555 }
556 }
557
558 if (flag_debug) {
559 fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
560 nsyms, HASH_BUCKETS,
561 (double)nsyms / (double)HASH_BUCKETS);
562 }
563
564 return errors != 0;
565}
566