Loading...
1// SPDX-License-Identifier: GPL-2.0-or-later
2/* Generate kernel symbol version hashes.
3 Copyright 1996, 1997 Linux International.
4
5 New implementation contributed by Richard Henderson <rth@tamu.edu>
6 Based on original work by Bjorn Ekwall <bj0rn@blox.se>
7
8 This file was part of the Linux modutils 2.4.22: moved back into the
9 kernel sources by Rusty Russell/Kai Germaschewski.
10
11 */
12
13#include <stdio.h>
14#include <string.h>
15#include <stdlib.h>
16#include <unistd.h>
17#include <assert.h>
18#include <stdarg.h>
19#ifdef __GNU_LIBRARY__
20#include <getopt.h>
21#endif /* __GNU_LIBRARY__ */
22
23#include "genksyms.h"
24/*----------------------------------------------------------------------*/
25
26#define HASH_BUCKETS 4096
27
28static struct symbol *symtab[HASH_BUCKETS];
29static FILE *debugfile;
30
31int cur_line = 1;
32char *cur_filename;
33int in_source_file;
34
35static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
36 flag_preserve, flag_warnings, flag_rel_crcs;
37
38static int errors;
39static int nsyms;
40
41static struct symbol *expansion_trail;
42static struct symbol *visited_symbols;
43
44static const struct {
45 int n;
46 const char *name;
47} symbol_types[] = {
48 [SYM_NORMAL] = { 0, NULL},
49 [SYM_TYPEDEF] = {'t', "typedef"},
50 [SYM_ENUM] = {'e', "enum"},
51 [SYM_STRUCT] = {'s', "struct"},
52 [SYM_UNION] = {'u', "union"},
53 [SYM_ENUM_CONST] = {'E', "enum constant"},
54};
55
56static int equal_list(struct string_list *a, struct string_list *b);
57static void print_list(FILE * f, struct string_list *list);
58static struct string_list *concat_list(struct string_list *start, ...);
59static struct string_list *mk_node(const char *string);
60static void print_location(void);
61static void print_type_name(enum symbol_type type, const char *name);
62
63/*----------------------------------------------------------------------*/
64
65static const unsigned int crctab32[] = {
66 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U,
67 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U,
68 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U,
69 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU,
70 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U,
71 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U,
72 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U,
73 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU,
74 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U,
75 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU,
76 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U,
77 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
78 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U,
79 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU,
80 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU,
81 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U,
82 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU,
83 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U,
84 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U,
85 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U,
86 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU,
87 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U,
88 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U,
89 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
90 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U,
91 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U,
92 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U,
93 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
94 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U,
95 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU,
96 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU,
97 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U,
98 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U,
99 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU,
100 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU,
101 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
102 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU,
103 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U,
104 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU,
105 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U,
106 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU,
107 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
108 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U,
109 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU,
110 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U,
111 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U,
112 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U,
113 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
114 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U,
115 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U,
116 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU,
117 0x2d02ef8dU
118};
119
120static unsigned long partial_crc32_one(unsigned char c, unsigned long crc)
121{
122 return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
123}
124
125static unsigned long partial_crc32(const char *s, unsigned long crc)
126{
127 while (*s)
128 crc = partial_crc32_one(*s++, crc);
129 return crc;
130}
131
132static unsigned long crc32(const char *s)
133{
134 return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
135}
136
137/*----------------------------------------------------------------------*/
138
139static enum symbol_type map_to_ns(enum symbol_type t)
140{
141 switch (t) {
142 case SYM_ENUM_CONST:
143 case SYM_NORMAL:
144 case SYM_TYPEDEF:
145 return SYM_NORMAL;
146 case SYM_ENUM:
147 case SYM_STRUCT:
148 case SYM_UNION:
149 return SYM_STRUCT;
150 }
151 return t;
152}
153
154struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact)
155{
156 unsigned long h = crc32(name) % HASH_BUCKETS;
157 struct symbol *sym;
158
159 for (sym = symtab[h]; sym; sym = sym->hash_next)
160 if (map_to_ns(sym->type) == map_to_ns(ns) &&
161 strcmp(name, sym->name) == 0 &&
162 sym->is_declared)
163 break;
164
165 if (exact && sym && sym->type != ns)
166 return NULL;
167 return sym;
168}
169
170static int is_unknown_symbol(struct symbol *sym)
171{
172 struct string_list *defn;
173
174 return ((sym->type == SYM_STRUCT ||
175 sym->type == SYM_UNION ||
176 sym->type == SYM_ENUM) &&
177 (defn = sym->defn) && defn->tag == SYM_NORMAL &&
178 strcmp(defn->string, "}") == 0 &&
179 (defn = defn->next) && defn->tag == SYM_NORMAL &&
180 strcmp(defn->string, "UNKNOWN") == 0 &&
181 (defn = defn->next) && defn->tag == SYM_NORMAL &&
182 strcmp(defn->string, "{") == 0);
183}
184
185static struct symbol *__add_symbol(const char *name, enum symbol_type type,
186 struct string_list *defn, int is_extern,
187 int is_reference)
188{
189 unsigned long h;
190 struct symbol *sym;
191 enum symbol_status status = STATUS_UNCHANGED;
192 /* The parser adds symbols in the order their declaration completes,
193 * so it is safe to store the value of the previous enum constant in
194 * a static variable.
195 */
196 static int enum_counter;
197 static struct string_list *last_enum_expr;
198
199 if (type == SYM_ENUM_CONST) {
200 if (defn) {
201 free_list(last_enum_expr, NULL);
202 last_enum_expr = copy_list_range(defn, NULL);
203 enum_counter = 1;
204 } else {
205 struct string_list *expr;
206 char buf[20];
207
208 snprintf(buf, sizeof(buf), "%d", enum_counter++);
209 if (last_enum_expr) {
210 expr = copy_list_range(last_enum_expr, NULL);
211 defn = concat_list(mk_node("("),
212 expr,
213 mk_node(")"),
214 mk_node("+"),
215 mk_node(buf), NULL);
216 } else {
217 defn = mk_node(buf);
218 }
219 }
220 } else if (type == SYM_ENUM) {
221 free_list(last_enum_expr, NULL);
222 last_enum_expr = NULL;
223 enum_counter = 0;
224 if (!name)
225 /* Anonymous enum definition, nothing more to do */
226 return NULL;
227 }
228
229 h = crc32(name) % HASH_BUCKETS;
230 for (sym = symtab[h]; sym; sym = sym->hash_next) {
231 if (map_to_ns(sym->type) == map_to_ns(type) &&
232 strcmp(name, sym->name) == 0) {
233 if (is_reference)
234 /* fall through */ ;
235 else if (sym->type == type &&
236 equal_list(sym->defn, defn)) {
237 if (!sym->is_declared && sym->is_override) {
238 print_location();
239 print_type_name(type, name);
240 fprintf(stderr, " modversion is "
241 "unchanged\n");
242 }
243 sym->is_declared = 1;
244 return sym;
245 } else if (!sym->is_declared) {
246 if (sym->is_override && flag_preserve) {
247 print_location();
248 fprintf(stderr, "ignoring ");
249 print_type_name(type, name);
250 fprintf(stderr, " modversion change\n");
251 sym->is_declared = 1;
252 return sym;
253 } else {
254 status = is_unknown_symbol(sym) ?
255 STATUS_DEFINED : STATUS_MODIFIED;
256 }
257 } else {
258 error_with_pos("redefinition of %s", name);
259 return sym;
260 }
261 break;
262 }
263 }
264
265 if (sym) {
266 struct symbol **psym;
267
268 for (psym = &symtab[h]; *psym; psym = &(*psym)->hash_next) {
269 if (*psym == sym) {
270 *psym = sym->hash_next;
271 break;
272 }
273 }
274 --nsyms;
275 }
276
277 sym = xmalloc(sizeof(*sym));
278 sym->name = name;
279 sym->type = type;
280 sym->defn = defn;
281 sym->expansion_trail = NULL;
282 sym->visited = NULL;
283 sym->is_extern = is_extern;
284
285 sym->hash_next = symtab[h];
286 symtab[h] = sym;
287
288 sym->is_declared = !is_reference;
289 sym->status = status;
290 sym->is_override = 0;
291
292 if (flag_debug) {
293 if (symbol_types[type].name)
294 fprintf(debugfile, "Defn for %s %s == <",
295 symbol_types[type].name, name);
296 else
297 fprintf(debugfile, "Defn for type%d %s == <",
298 type, name);
299 if (is_extern)
300 fputs("extern ", debugfile);
301 print_list(debugfile, defn);
302 fputs(">\n", debugfile);
303 }
304
305 ++nsyms;
306 return sym;
307}
308
309struct symbol *add_symbol(const char *name, enum symbol_type type,
310 struct string_list *defn, int is_extern)
311{
312 return __add_symbol(name, type, defn, is_extern, 0);
313}
314
315static struct symbol *add_reference_symbol(const char *name, enum symbol_type type,
316 struct string_list *defn, int is_extern)
317{
318 return __add_symbol(name, type, defn, is_extern, 1);
319}
320
321/*----------------------------------------------------------------------*/
322
323void free_node(struct string_list *node)
324{
325 free(node->string);
326 free(node);
327}
328
329void free_list(struct string_list *s, struct string_list *e)
330{
331 while (s != e) {
332 struct string_list *next = s->next;
333 free_node(s);
334 s = next;
335 }
336}
337
338static struct string_list *mk_node(const char *string)
339{
340 struct string_list *newnode;
341
342 newnode = xmalloc(sizeof(*newnode));
343 newnode->string = xstrdup(string);
344 newnode->tag = SYM_NORMAL;
345 newnode->next = NULL;
346
347 return newnode;
348}
349
350static struct string_list *concat_list(struct string_list *start, ...)
351{
352 va_list ap;
353 struct string_list *n, *n2;
354
355 if (!start)
356 return NULL;
357 for (va_start(ap, start); (n = va_arg(ap, struct string_list *));) {
358 for (n2 = n; n2->next; n2 = n2->next)
359 ;
360 n2->next = start;
361 start = n;
362 }
363 va_end(ap);
364 return start;
365}
366
367struct string_list *copy_node(struct string_list *node)
368{
369 struct string_list *newnode;
370
371 newnode = xmalloc(sizeof(*newnode));
372 newnode->string = xstrdup(node->string);
373 newnode->tag = node->tag;
374
375 return newnode;
376}
377
378struct string_list *copy_list_range(struct string_list *start,
379 struct string_list *end)
380{
381 struct string_list *res, *n;
382
383 if (start == end)
384 return NULL;
385 n = res = copy_node(start);
386 for (start = start->next; start != end; start = start->next) {
387 n->next = copy_node(start);
388 n = n->next;
389 }
390 n->next = NULL;
391 return res;
392}
393
394static int equal_list(struct string_list *a, struct string_list *b)
395{
396 while (a && b) {
397 if (a->tag != b->tag || strcmp(a->string, b->string))
398 return 0;
399 a = a->next;
400 b = b->next;
401 }
402
403 return !a && !b;
404}
405
406#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
407
408static struct string_list *read_node(FILE *f)
409{
410 char buffer[256];
411 struct string_list node = {
412 .string = buffer,
413 .tag = SYM_NORMAL };
414 int c, in_string = 0;
415
416 while ((c = fgetc(f)) != EOF) {
417 if (!in_string && c == ' ') {
418 if (node.string == buffer)
419 continue;
420 break;
421 } else if (c == '"') {
422 in_string = !in_string;
423 } else if (c == '\n') {
424 if (node.string == buffer)
425 return NULL;
426 ungetc(c, f);
427 break;
428 }
429 if (node.string >= buffer + sizeof(buffer) - 1) {
430 fprintf(stderr, "Token too long\n");
431 exit(1);
432 }
433 *node.string++ = c;
434 }
435 if (node.string == buffer)
436 return NULL;
437 *node.string = 0;
438 node.string = buffer;
439
440 if (node.string[1] == '#') {
441 size_t n;
442
443 for (n = 0; n < ARRAY_SIZE(symbol_types); n++) {
444 if (node.string[0] == symbol_types[n].n) {
445 node.tag = n;
446 node.string += 2;
447 return copy_node(&node);
448 }
449 }
450 fprintf(stderr, "Unknown type %c\n", node.string[0]);
451 exit(1);
452 }
453 return copy_node(&node);
454}
455
456static void read_reference(FILE *f)
457{
458 while (!feof(f)) {
459 struct string_list *defn = NULL;
460 struct string_list *sym, *def;
461 int is_extern = 0, is_override = 0;
462 struct symbol *subsym;
463
464 sym = read_node(f);
465 if (sym && sym->tag == SYM_NORMAL &&
466 !strcmp(sym->string, "override")) {
467 is_override = 1;
468 free_node(sym);
469 sym = read_node(f);
470 }
471 if (!sym)
472 continue;
473 def = read_node(f);
474 if (def && def->tag == SYM_NORMAL &&
475 !strcmp(def->string, "extern")) {
476 is_extern = 1;
477 free_node(def);
478 def = read_node(f);
479 }
480 while (def) {
481 def->next = defn;
482 defn = def;
483 def = read_node(f);
484 }
485 subsym = add_reference_symbol(xstrdup(sym->string), sym->tag,
486 defn, is_extern);
487 subsym->is_override = is_override;
488 free_node(sym);
489 }
490}
491
492static void print_node(FILE * f, struct string_list *list)
493{
494 if (symbol_types[list->tag].n) {
495 putc(symbol_types[list->tag].n, f);
496 putc('#', f);
497 }
498 fputs(list->string, f);
499}
500
501static void print_list(FILE * f, struct string_list *list)
502{
503 struct string_list **e, **b;
504 struct string_list *tmp, **tmp2;
505 int elem = 1;
506
507 if (list == NULL) {
508 fputs("(nil)", f);
509 return;
510 }
511
512 tmp = list;
513 while ((tmp = tmp->next) != NULL)
514 elem++;
515
516 b = alloca(elem * sizeof(*e));
517 e = b + elem;
518 tmp2 = e - 1;
519
520 (*tmp2--) = list;
521 while ((list = list->next) != NULL)
522 *(tmp2--) = list;
523
524 while (b != e) {
525 print_node(f, *b++);
526 putc(' ', f);
527 }
528}
529
530static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
531{
532 struct string_list *list = sym->defn;
533 struct string_list **e, **b;
534 struct string_list *tmp, **tmp2;
535 int elem = 1;
536
537 if (!list)
538 return crc;
539
540 tmp = list;
541 while ((tmp = tmp->next) != NULL)
542 elem++;
543
544 b = alloca(elem * sizeof(*e));
545 e = b + elem;
546 tmp2 = e - 1;
547
548 *(tmp2--) = list;
549 while ((list = list->next) != NULL)
550 *(tmp2--) = list;
551
552 while (b != e) {
553 struct string_list *cur;
554 struct symbol *subsym;
555
556 cur = *(b++);
557 switch (cur->tag) {
558 case SYM_NORMAL:
559 if (flag_dump_defs)
560 fprintf(debugfile, "%s ", cur->string);
561 crc = partial_crc32(cur->string, crc);
562 crc = partial_crc32_one(' ', crc);
563 break;
564
565 case SYM_ENUM_CONST:
566 case SYM_TYPEDEF:
567 subsym = find_symbol(cur->string, cur->tag, 0);
568 /* FIXME: Bad reference files can segfault here. */
569 if (subsym->expansion_trail) {
570 if (flag_dump_defs)
571 fprintf(debugfile, "%s ", cur->string);
572 crc = partial_crc32(cur->string, crc);
573 crc = partial_crc32_one(' ', crc);
574 } else {
575 subsym->expansion_trail = expansion_trail;
576 expansion_trail = subsym;
577 crc = expand_and_crc_sym(subsym, crc);
578 }
579 break;
580
581 case SYM_STRUCT:
582 case SYM_UNION:
583 case SYM_ENUM:
584 subsym = find_symbol(cur->string, cur->tag, 0);
585 if (!subsym) {
586 struct string_list *n;
587
588 error_with_pos("expand undefined %s %s",
589 symbol_types[cur->tag].name,
590 cur->string);
591 n = concat_list(mk_node
592 (symbol_types[cur->tag].name),
593 mk_node(cur->string),
594 mk_node("{"),
595 mk_node("UNKNOWN"),
596 mk_node("}"), NULL);
597 subsym =
598 add_symbol(cur->string, cur->tag, n, 0);
599 }
600 if (subsym->expansion_trail) {
601 if (flag_dump_defs) {
602 fprintf(debugfile, "%s %s ",
603 symbol_types[cur->tag].name,
604 cur->string);
605 }
606
607 crc = partial_crc32(symbol_types[cur->tag].name,
608 crc);
609 crc = partial_crc32_one(' ', crc);
610 crc = partial_crc32(cur->string, crc);
611 crc = partial_crc32_one(' ', crc);
612 } else {
613 subsym->expansion_trail = expansion_trail;
614 expansion_trail = subsym;
615 crc = expand_and_crc_sym(subsym, crc);
616 }
617 break;
618 }
619 }
620
621 {
622 static struct symbol **end = &visited_symbols;
623
624 if (!sym->visited) {
625 *end = sym;
626 end = &sym->visited;
627 sym->visited = (struct symbol *)-1L;
628 }
629 }
630
631 return crc;
632}
633
634void export_symbol(const char *name)
635{
636 struct symbol *sym;
637
638 sym = find_symbol(name, SYM_NORMAL, 0);
639 if (!sym)
640 error_with_pos("export undefined symbol %s", name);
641 else {
642 unsigned long crc;
643 int has_changed = 0;
644
645 if (flag_dump_defs)
646 fprintf(debugfile, "Export %s == <", name);
647
648 expansion_trail = (struct symbol *)-1L;
649
650 sym->expansion_trail = expansion_trail;
651 expansion_trail = sym;
652 crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff;
653
654 sym = expansion_trail;
655 while (sym != (struct symbol *)-1L) {
656 struct symbol *n = sym->expansion_trail;
657
658 if (sym->status != STATUS_UNCHANGED) {
659 if (!has_changed) {
660 print_location();
661 fprintf(stderr, "%s: %s: modversion "
662 "changed because of changes "
663 "in ", flag_preserve ? "error" :
664 "warning", name);
665 } else
666 fprintf(stderr, ", ");
667 print_type_name(sym->type, sym->name);
668 if (sym->status == STATUS_DEFINED)
669 fprintf(stderr, " (became defined)");
670 has_changed = 1;
671 if (flag_preserve)
672 errors++;
673 }
674 sym->expansion_trail = 0;
675 sym = n;
676 }
677 if (has_changed)
678 fprintf(stderr, "\n");
679
680 if (flag_dump_defs)
681 fputs(">\n", debugfile);
682
683 /* Used as a linker script. */
684 printf(!flag_rel_crcs ? "__crc_%s = 0x%08lx;\n" :
685 "SECTIONS { .rodata : ALIGN(4) { "
686 "__crc_%s = .; LONG(0x%08lx); } }\n",
687 name, crc);
688 }
689}
690
691/*----------------------------------------------------------------------*/
692
693static void print_location(void)
694{
695 fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line);
696}
697
698static void print_type_name(enum symbol_type type, const char *name)
699{
700 if (symbol_types[type].name)
701 fprintf(stderr, "%s %s", symbol_types[type].name, name);
702 else
703 fprintf(stderr, "%s", name);
704}
705
706void error_with_pos(const char *fmt, ...)
707{
708 va_list args;
709
710 if (flag_warnings) {
711 print_location();
712
713 va_start(args, fmt);
714 vfprintf(stderr, fmt, args);
715 va_end(args);
716 putc('\n', stderr);
717
718 errors++;
719 }
720}
721
722static void genksyms_usage(void)
723{
724 fputs("Usage:\n" "genksyms [-adDTwqhVR] > /path/to/.tmp_obj.ver\n" "\n"
725#ifdef __GNU_LIBRARY__
726 " -s, --symbol-prefix Select symbol prefix\n"
727 " -d, --debug Increment the debug level (repeatable)\n"
728 " -D, --dump Dump expanded symbol defs (for debugging only)\n"
729 " -r, --reference file Read reference symbols from a file\n"
730 " -T, --dump-types file Dump expanded types into file\n"
731 " -p, --preserve Preserve reference modversions or fail\n"
732 " -w, --warnings Enable warnings\n"
733 " -q, --quiet Disable warnings (default)\n"
734 " -h, --help Print this message\n"
735 " -V, --version Print the release version\n"
736 " -R, --relative-crc Emit section relative symbol CRCs\n"
737#else /* __GNU_LIBRARY__ */
738 " -s Select symbol prefix\n"
739 " -d Increment the debug level (repeatable)\n"
740 " -D Dump expanded symbol defs (for debugging only)\n"
741 " -r file Read reference symbols from a file\n"
742 " -T file Dump expanded types into file\n"
743 " -p Preserve reference modversions or fail\n"
744 " -w Enable warnings\n"
745 " -q Disable warnings (default)\n"
746 " -h Print this message\n"
747 " -V Print the release version\n"
748 " -R Emit section relative symbol CRCs\n"
749#endif /* __GNU_LIBRARY__ */
750 , stderr);
751}
752
753int main(int argc, char **argv)
754{
755 FILE *dumpfile = NULL, *ref_file = NULL;
756 int o;
757
758#ifdef __GNU_LIBRARY__
759 struct option long_opts[] = {
760 {"debug", 0, 0, 'd'},
761 {"warnings", 0, 0, 'w'},
762 {"quiet", 0, 0, 'q'},
763 {"dump", 0, 0, 'D'},
764 {"reference", 1, 0, 'r'},
765 {"dump-types", 1, 0, 'T'},
766 {"preserve", 0, 0, 'p'},
767 {"version", 0, 0, 'V'},
768 {"help", 0, 0, 'h'},
769 {"relative-crc", 0, 0, 'R'},
770 {0, 0, 0, 0}
771 };
772
773 while ((o = getopt_long(argc, argv, "s:dwqVDr:T:phR",
774 &long_opts[0], NULL)) != EOF)
775#else /* __GNU_LIBRARY__ */
776 while ((o = getopt(argc, argv, "s:dwqVDr:T:phR")) != EOF)
777#endif /* __GNU_LIBRARY__ */
778 switch (o) {
779 case 'd':
780 flag_debug++;
781 break;
782 case 'w':
783 flag_warnings = 1;
784 break;
785 case 'q':
786 flag_warnings = 0;
787 break;
788 case 'V':
789 fputs("genksyms version 2.5.60\n", stderr);
790 break;
791 case 'D':
792 flag_dump_defs = 1;
793 break;
794 case 'r':
795 flag_reference = 1;
796 ref_file = fopen(optarg, "r");
797 if (!ref_file) {
798 perror(optarg);
799 return 1;
800 }
801 break;
802 case 'T':
803 flag_dump_types = 1;
804 dumpfile = fopen(optarg, "w");
805 if (!dumpfile) {
806 perror(optarg);
807 return 1;
808 }
809 break;
810 case 'p':
811 flag_preserve = 1;
812 break;
813 case 'h':
814 genksyms_usage();
815 return 0;
816 case 'R':
817 flag_rel_crcs = 1;
818 break;
819 default:
820 genksyms_usage();
821 return 1;
822 }
823 {
824 extern int yydebug;
825 extern int yy_flex_debug;
826
827 yydebug = (flag_debug > 1);
828 yy_flex_debug = (flag_debug > 2);
829
830 debugfile = stderr;
831 /* setlinebuf(debugfile); */
832 }
833
834 if (flag_reference) {
835 read_reference(ref_file);
836 fclose(ref_file);
837 }
838
839 yyparse();
840
841 if (flag_dump_types && visited_symbols) {
842 while (visited_symbols != (struct symbol *)-1L) {
843 struct symbol *sym = visited_symbols;
844
845 if (sym->is_override)
846 fputs("override ", dumpfile);
847 if (symbol_types[sym->type].n) {
848 putc(symbol_types[sym->type].n, dumpfile);
849 putc('#', dumpfile);
850 }
851 fputs(sym->name, dumpfile);
852 putc(' ', dumpfile);
853 if (sym->is_extern)
854 fputs("extern ", dumpfile);
855 print_list(dumpfile, sym->defn);
856 putc('\n', dumpfile);
857
858 visited_symbols = sym->visited;
859 sym->visited = NULL;
860 }
861 }
862
863 if (flag_debug) {
864 fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
865 nsyms, HASH_BUCKETS,
866 (double)nsyms / (double)HASH_BUCKETS);
867 }
868
869 if (dumpfile)
870 fclose(dumpfile);
871
872 return errors != 0;
873}
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#define HASH_BUCKETS 4096
38
39static struct symbol *symtab[HASH_BUCKETS];
40static FILE *debugfile;
41
42int cur_line = 1;
43char *cur_filename, *source_file;
44int in_source_file;
45
46static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
47 flag_preserve, flag_warnings;
48static const char *arch = "";
49static const char *mod_prefix = "";
50
51static int errors;
52static int nsyms;
53
54static struct symbol *expansion_trail;
55static struct symbol *visited_symbols;
56
57static const struct {
58 int n;
59 const char *name;
60} symbol_types[] = {
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"},
67};
68
69static int equal_list(struct string_list *a, struct string_list *b);
70static void print_list(FILE * f, struct string_list *list);
71static struct string_list *concat_list(struct string_list *start, ...);
72static struct string_list *mk_node(const char *string);
73static void print_location(void);
74static void print_type_name(enum symbol_type type, const char *name);
75
76/*----------------------------------------------------------------------*/
77
78static 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,
130 0x2d02ef8dU
131};
132
133static unsigned long partial_crc32_one(unsigned char c, unsigned long crc)
134{
135 return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
136}
137
138static unsigned long partial_crc32(const char *s, unsigned long crc)
139{
140 while (*s)
141 crc = partial_crc32_one(*s++, crc);
142 return crc;
143}
144
145static unsigned long crc32(const char *s)
146{
147 return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
148}
149
150/*----------------------------------------------------------------------*/
151
152static enum symbol_type map_to_ns(enum symbol_type t)
153{
154 switch (t) {
155 case SYM_ENUM_CONST:
156 case SYM_NORMAL:
157 case SYM_TYPEDEF:
158 return SYM_NORMAL;
159 case SYM_ENUM:
160 case SYM_STRUCT:
161 case SYM_UNION:
162 return SYM_STRUCT;
163 }
164 return t;
165}
166
167struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact)
168{
169 unsigned long h = crc32(name) % HASH_BUCKETS;
170 struct symbol *sym;
171
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 &&
175 sym->is_declared)
176 break;
177
178 if (exact && sym && sym->type != ns)
179 return NULL;
180 return sym;
181}
182
183static int is_unknown_symbol(struct symbol *sym)
184{
185 struct string_list *defn;
186
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);
196}
197
198static struct symbol *__add_symbol(const char *name, enum symbol_type type,
199 struct string_list *defn, int is_extern,
200 int is_reference)
201{
202 unsigned long h;
203 struct symbol *sym;
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
207 * a static variable.
208 */
209 static int enum_counter;
210 static struct string_list *last_enum_expr;
211
212 if (type == SYM_ENUM_CONST) {
213 if (defn) {
214 free_list(last_enum_expr, NULL);
215 last_enum_expr = copy_list_range(defn, NULL);
216 enum_counter = 1;
217 } else {
218 struct string_list *expr;
219 char buf[20];
220
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("("),
225 expr,
226 mk_node(")"),
227 mk_node("+"),
228 mk_node(buf), NULL);
229 } else {
230 defn = mk_node(buf);
231 }
232 }
233 } else if (type == SYM_ENUM) {
234 free_list(last_enum_expr, NULL);
235 last_enum_expr = NULL;
236 enum_counter = 0;
237 if (!name)
238 /* Anonymous enum definition, nothing more to do */
239 return NULL;
240 }
241
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) {
246 if (is_reference)
247 /* fall through */ ;
248 else if (sym->type == type &&
249 equal_list(sym->defn, defn)) {
250 if (!sym->is_declared && sym->is_override) {
251 print_location();
252 print_type_name(type, name);
253 fprintf(stderr, " modversion is "
254 "unchanged\n");
255 }
256 sym->is_declared = 1;
257 return sym;
258 } else if (!sym->is_declared) {
259 if (sym->is_override && flag_preserve) {
260 print_location();
261 fprintf(stderr, "ignoring ");
262 print_type_name(type, name);
263 fprintf(stderr, " modversion change\n");
264 sym->is_declared = 1;
265 return sym;
266 } else {
267 status = is_unknown_symbol(sym) ?
268 STATUS_DEFINED : STATUS_MODIFIED;
269 }
270 } else {
271 error_with_pos("redefinition of %s", name);
272 return sym;
273 }
274 break;
275 }
276 }
277
278 if (sym) {
279 struct symbol **psym;
280
281 for (psym = &symtab[h]; *psym; psym = &(*psym)->hash_next) {
282 if (*psym == sym) {
283 *psym = sym->hash_next;
284 break;
285 }
286 }
287 --nsyms;
288 }
289
290 sym = xmalloc(sizeof(*sym));
291 sym->name = name;
292 sym->type = type;
293 sym->defn = defn;
294 sym->expansion_trail = NULL;
295 sym->visited = NULL;
296 sym->is_extern = is_extern;
297
298 sym->hash_next = symtab[h];
299 symtab[h] = sym;
300
301 sym->is_declared = !is_reference;
302 sym->status = status;
303 sym->is_override = 0;
304
305 if (flag_debug) {
306 if (symbol_types[type].name)
307 fprintf(debugfile, "Defn for %s %s == <",
308 symbol_types[type].name, name);
309 else
310 fprintf(debugfile, "Defn for type%d %s == <",
311 type, name);
312 if (is_extern)
313 fputs("extern ", debugfile);
314 print_list(debugfile, defn);
315 fputs(">\n", debugfile);
316 }
317
318 ++nsyms;
319 return sym;
320}
321
322struct symbol *add_symbol(const char *name, enum symbol_type type,
323 struct string_list *defn, int is_extern)
324{
325 return __add_symbol(name, type, defn, is_extern, 0);
326}
327
328static struct symbol *add_reference_symbol(const char *name, enum symbol_type type,
329 struct string_list *defn, int is_extern)
330{
331 return __add_symbol(name, type, defn, is_extern, 1);
332}
333
334/*----------------------------------------------------------------------*/
335
336void free_node(struct string_list *node)
337{
338 free(node->string);
339 free(node);
340}
341
342void free_list(struct string_list *s, struct string_list *e)
343{
344 while (s != e) {
345 struct string_list *next = s->next;
346 free_node(s);
347 s = next;
348 }
349}
350
351static struct string_list *mk_node(const char *string)
352{
353 struct string_list *newnode;
354
355 newnode = xmalloc(sizeof(*newnode));
356 newnode->string = xstrdup(string);
357 newnode->tag = SYM_NORMAL;
358 newnode->next = NULL;
359
360 return newnode;
361}
362
363static struct string_list *concat_list(struct string_list *start, ...)
364{
365 va_list ap;
366 struct string_list *n, *n2;
367
368 if (!start)
369 return NULL;
370 for (va_start(ap, start); (n = va_arg(ap, struct string_list *));) {
371 for (n2 = n; n2->next; n2 = n2->next)
372 ;
373 n2->next = start;
374 start = n;
375 }
376 va_end(ap);
377 return start;
378}
379
380struct string_list *copy_node(struct string_list *node)
381{
382 struct string_list *newnode;
383
384 newnode = xmalloc(sizeof(*newnode));
385 newnode->string = xstrdup(node->string);
386 newnode->tag = node->tag;
387
388 return newnode;
389}
390
391struct string_list *copy_list_range(struct string_list *start,
392 struct string_list *end)
393{
394 struct string_list *res, *n;
395
396 if (start == end)
397 return NULL;
398 n = res = copy_node(start);
399 for (start = start->next; start != end; start = start->next) {
400 n->next = copy_node(start);
401 n = n->next;
402 }
403 n->next = NULL;
404 return res;
405}
406
407static int equal_list(struct string_list *a, struct string_list *b)
408{
409 while (a && b) {
410 if (a->tag != b->tag || strcmp(a->string, b->string))
411 return 0;
412 a = a->next;
413 b = b->next;
414 }
415
416 return !a && !b;
417}
418
419#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
420
421static struct string_list *read_node(FILE *f)
422{
423 char buffer[256];
424 struct string_list node = {
425 .string = buffer,
426 .tag = SYM_NORMAL };
427 int c;
428
429 while ((c = fgetc(f)) != EOF) {
430 if (c == ' ') {
431 if (node.string == buffer)
432 continue;
433 break;
434 } else if (c == '\n') {
435 if (node.string == buffer)
436 return NULL;
437 ungetc(c, f);
438 break;
439 }
440 if (node.string >= buffer + sizeof(buffer) - 1) {
441 fprintf(stderr, "Token too long\n");
442 exit(1);
443 }
444 *node.string++ = c;
445 }
446 if (node.string == buffer)
447 return NULL;
448 *node.string = 0;
449 node.string = buffer;
450
451 if (node.string[1] == '#') {
452 size_t n;
453
454 for (n = 0; n < ARRAY_SIZE(symbol_types); n++) {
455 if (node.string[0] == symbol_types[n].n) {
456 node.tag = n;
457 node.string += 2;
458 return copy_node(&node);
459 }
460 }
461 fprintf(stderr, "Unknown type %c\n", node.string[0]);
462 exit(1);
463 }
464 return copy_node(&node);
465}
466
467static void read_reference(FILE *f)
468{
469 while (!feof(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;
474
475 sym = read_node(f);
476 if (sym && sym->tag == SYM_NORMAL &&
477 !strcmp(sym->string, "override")) {
478 is_override = 1;
479 free_node(sym);
480 sym = read_node(f);
481 }
482 if (!sym)
483 continue;
484 def = read_node(f);
485 if (def && def->tag == SYM_NORMAL &&
486 !strcmp(def->string, "extern")) {
487 is_extern = 1;
488 free_node(def);
489 def = read_node(f);
490 }
491 while (def) {
492 def->next = defn;
493 defn = def;
494 def = read_node(f);
495 }
496 subsym = add_reference_symbol(xstrdup(sym->string), sym->tag,
497 defn, is_extern);
498 subsym->is_override = is_override;
499 free_node(sym);
500 }
501}
502
503static void print_node(FILE * f, struct string_list *list)
504{
505 if (symbol_types[list->tag].n) {
506 putc(symbol_types[list->tag].n, f);
507 putc('#', f);
508 }
509 fputs(list->string, f);
510}
511
512static void print_list(FILE * f, struct string_list *list)
513{
514 struct string_list **e, **b;
515 struct string_list *tmp, **tmp2;
516 int elem = 1;
517
518 if (list == NULL) {
519 fputs("(nil)", f);
520 return;
521 }
522
523 tmp = list;
524 while ((tmp = tmp->next) != NULL)
525 elem++;
526
527 b = alloca(elem * sizeof(*e));
528 e = b + elem;
529 tmp2 = e - 1;
530
531 (*tmp2--) = list;
532 while ((list = list->next) != NULL)
533 *(tmp2--) = list;
534
535 while (b != e) {
536 print_node(f, *b++);
537 putc(' ', f);
538 }
539}
540
541static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
542{
543 struct string_list *list = sym->defn;
544 struct string_list **e, **b;
545 struct string_list *tmp, **tmp2;
546 int elem = 1;
547
548 if (!list)
549 return crc;
550
551 tmp = list;
552 while ((tmp = tmp->next) != NULL)
553 elem++;
554
555 b = alloca(elem * sizeof(*e));
556 e = b + elem;
557 tmp2 = e - 1;
558
559 *(tmp2--) = list;
560 while ((list = list->next) != NULL)
561 *(tmp2--) = list;
562
563 while (b != e) {
564 struct string_list *cur;
565 struct symbol *subsym;
566
567 cur = *(b++);
568 switch (cur->tag) {
569 case SYM_NORMAL:
570 if (flag_dump_defs)
571 fprintf(debugfile, "%s ", cur->string);
572 crc = partial_crc32(cur->string, crc);
573 crc = partial_crc32_one(' ', crc);
574 break;
575
576 case SYM_ENUM_CONST:
577 case SYM_TYPEDEF:
578 subsym = find_symbol(cur->string, cur->tag, 0);
579 /* FIXME: Bad reference files can segfault here. */
580 if (subsym->expansion_trail) {
581 if (flag_dump_defs)
582 fprintf(debugfile, "%s ", cur->string);
583 crc = partial_crc32(cur->string, crc);
584 crc = partial_crc32_one(' ', crc);
585 } else {
586 subsym->expansion_trail = expansion_trail;
587 expansion_trail = subsym;
588 crc = expand_and_crc_sym(subsym, crc);
589 }
590 break;
591
592 case SYM_STRUCT:
593 case SYM_UNION:
594 case SYM_ENUM:
595 subsym = find_symbol(cur->string, cur->tag, 0);
596 if (!subsym) {
597 struct string_list *n;
598
599 error_with_pos("expand undefined %s %s",
600 symbol_types[cur->tag].name,
601 cur->string);
602 n = concat_list(mk_node
603 (symbol_types[cur->tag].name),
604 mk_node(cur->string),
605 mk_node("{"),
606 mk_node("UNKNOWN"),
607 mk_node("}"), NULL);
608 subsym =
609 add_symbol(cur->string, cur->tag, n, 0);
610 }
611 if (subsym->expansion_trail) {
612 if (flag_dump_defs) {
613 fprintf(debugfile, "%s %s ",
614 symbol_types[cur->tag].name,
615 cur->string);
616 }
617
618 crc = partial_crc32(symbol_types[cur->tag].name,
619 crc);
620 crc = partial_crc32_one(' ', crc);
621 crc = partial_crc32(cur->string, crc);
622 crc = partial_crc32_one(' ', crc);
623 } else {
624 subsym->expansion_trail = expansion_trail;
625 expansion_trail = subsym;
626 crc = expand_and_crc_sym(subsym, crc);
627 }
628 break;
629 }
630 }
631
632 {
633 static struct symbol **end = &visited_symbols;
634
635 if (!sym->visited) {
636 *end = sym;
637 end = &sym->visited;
638 sym->visited = (struct symbol *)-1L;
639 }
640 }
641
642 return crc;
643}
644
645void export_symbol(const char *name)
646{
647 struct symbol *sym;
648
649 sym = find_symbol(name, SYM_NORMAL, 0);
650 if (!sym)
651 error_with_pos("export undefined symbol %s", name);
652 else {
653 unsigned long crc;
654 int has_changed = 0;
655
656 if (flag_dump_defs)
657 fprintf(debugfile, "Export %s == <", name);
658
659 expansion_trail = (struct symbol *)-1L;
660
661 sym->expansion_trail = expansion_trail;
662 expansion_trail = sym;
663 crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff;
664
665 sym = expansion_trail;
666 while (sym != (struct symbol *)-1L) {
667 struct symbol *n = sym->expansion_trail;
668
669 if (sym->status != STATUS_UNCHANGED) {
670 if (!has_changed) {
671 print_location();
672 fprintf(stderr, "%s: %s: modversion "
673 "changed because of changes "
674 "in ", flag_preserve ? "error" :
675 "warning", name);
676 } else
677 fprintf(stderr, ", ");
678 print_type_name(sym->type, sym->name);
679 if (sym->status == STATUS_DEFINED)
680 fprintf(stderr, " (became defined)");
681 has_changed = 1;
682 if (flag_preserve)
683 errors++;
684 }
685 sym->expansion_trail = 0;
686 sym = n;
687 }
688 if (has_changed)
689 fprintf(stderr, "\n");
690
691 if (flag_dump_defs)
692 fputs(">\n", debugfile);
693
694 /* Used as a linker script. */
695 printf("%s__crc_%s = 0x%08lx ;\n", mod_prefix, name, crc);
696 }
697}
698
699/*----------------------------------------------------------------------*/
700
701static void print_location(void)
702{
703 fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line);
704}
705
706static void print_type_name(enum symbol_type type, const char *name)
707{
708 if (symbol_types[type].name)
709 fprintf(stderr, "%s %s", symbol_types[type].name, name);
710 else
711 fprintf(stderr, "%s", name);
712}
713
714void error_with_pos(const char *fmt, ...)
715{
716 va_list args;
717
718 if (flag_warnings) {
719 print_location();
720
721 va_start(args, fmt);
722 vfprintf(stderr, fmt, args);
723 va_end(args);
724 putc('\n', stderr);
725
726 errors++;
727 }
728}
729
730static void genksyms_usage(void)
731{
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__ */
756 , stderr);
757}
758
759int main(int argc, char **argv)
760{
761 FILE *dumpfile = NULL, *ref_file = NULL;
762 int o;
763
764#ifdef __GNU_LIBRARY__
765 struct option long_opts[] = {
766 {"arch", 1, 0, 'a'},
767 {"debug", 0, 0, 'd'},
768 {"warnings", 0, 0, 'w'},
769 {"quiet", 0, 0, 'q'},
770 {"dump", 0, 0, 'D'},
771 {"reference", 1, 0, 'r'},
772 {"dump-types", 1, 0, 'T'},
773 {"preserve", 0, 0, 'p'},
774 {"version", 0, 0, 'V'},
775 {"help", 0, 0, 'h'},
776 {0, 0, 0, 0}
777 };
778
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__ */
784 switch (o) {
785 case 'a':
786 arch = optarg;
787 break;
788 case 'd':
789 flag_debug++;
790 break;
791 case 'w':
792 flag_warnings = 1;
793 break;
794 case 'q':
795 flag_warnings = 0;
796 break;
797 case 'V':
798 fputs("genksyms version 2.5.60\n", stderr);
799 break;
800 case 'D':
801 flag_dump_defs = 1;
802 break;
803 case 'r':
804 flag_reference = 1;
805 ref_file = fopen(optarg, "r");
806 if (!ref_file) {
807 perror(optarg);
808 return 1;
809 }
810 break;
811 case 'T':
812 flag_dump_types = 1;
813 dumpfile = fopen(optarg, "w");
814 if (!dumpfile) {
815 perror(optarg);
816 return 1;
817 }
818 break;
819 case 'p':
820 flag_preserve = 1;
821 break;
822 case 'h':
823 genksyms_usage();
824 return 0;
825 default:
826 genksyms_usage();
827 return 1;
828 }
829 if ((strcmp(arch, "h8300") == 0) || (strcmp(arch, "blackfin") == 0))
830 mod_prefix = "_";
831 {
832 extern int yydebug;
833 extern int yy_flex_debug;
834
835 yydebug = (flag_debug > 1);
836 yy_flex_debug = (flag_debug > 2);
837
838 debugfile = stderr;
839 /* setlinebuf(debugfile); */
840 }
841
842 if (flag_reference) {
843 read_reference(ref_file);
844 fclose(ref_file);
845 }
846
847 yyparse();
848
849 if (flag_dump_types && visited_symbols) {
850 while (visited_symbols != (struct symbol *)-1L) {
851 struct symbol *sym = visited_symbols;
852
853 if (sym->is_override)
854 fputs("override ", dumpfile);
855 if (symbol_types[sym->type].n) {
856 putc(symbol_types[sym->type].n, dumpfile);
857 putc('#', dumpfile);
858 }
859 fputs(sym->name, dumpfile);
860 putc(' ', dumpfile);
861 if (sym->is_extern)
862 fputs("extern ", dumpfile);
863 print_list(dumpfile, sym->defn);
864 putc('\n', dumpfile);
865
866 visited_symbols = sym->visited;
867 sym->visited = NULL;
868 }
869 }
870
871 if (flag_debug) {
872 fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
873 nsyms, HASH_BUCKETS,
874 (double)nsyms / (double)HASH_BUCKETS);
875 }
876
877 return errors != 0;
878}