]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - scripts/genksyms/genksyms.c
Merge tag 'jfs-4.18' of git://github.com/kleikamp/linux-shaggy
[mirror_ubuntu-jammy-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 #define HASH_BUCKETS 4096
38
39 static struct symbol *symtab[HASH_BUCKETS];
40 static FILE *debugfile;
41
42 int cur_line = 1;
43 char *cur_filename, *source_file;
44 int in_source_file;
45
46 static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
47 flag_preserve, flag_warnings, flag_rel_crcs;
48
49 static int errors;
50 static int nsyms;
51
52 static struct symbol *expansion_trail;
53 static struct symbol *visited_symbols;
54
55 static const struct {
56 int n;
57 const char *name;
58 } symbol_types[] = {
59 [SYM_NORMAL] = { 0, NULL},
60 [SYM_TYPEDEF] = {'t', "typedef"},
61 [SYM_ENUM] = {'e', "enum"},
62 [SYM_STRUCT] = {'s', "struct"},
63 [SYM_UNION] = {'u', "union"},
64 [SYM_ENUM_CONST] = {'E', "enum constant"},
65 };
66
67 static int equal_list(struct string_list *a, struct string_list *b);
68 static void print_list(FILE * f, struct string_list *list);
69 static struct string_list *concat_list(struct string_list *start, ...);
70 static struct string_list *mk_node(const char *string);
71 static void print_location(void);
72 static void print_type_name(enum symbol_type type, const char *name);
73
74 /*----------------------------------------------------------------------*/
75
76 static const unsigned int crctab32[] = {
77 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U,
78 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U,
79 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U,
80 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU,
81 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U,
82 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U,
83 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U,
84 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU,
85 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U,
86 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU,
87 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U,
88 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
89 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U,
90 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU,
91 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU,
92 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U,
93 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU,
94 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U,
95 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U,
96 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U,
97 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU,
98 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U,
99 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U,
100 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
101 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U,
102 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U,
103 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U,
104 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
105 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U,
106 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU,
107 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU,
108 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U,
109 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U,
110 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU,
111 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU,
112 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
113 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU,
114 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U,
115 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU,
116 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U,
117 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU,
118 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
119 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U,
120 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU,
121 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U,
122 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U,
123 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U,
124 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
125 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U,
126 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U,
127 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU,
128 0x2d02ef8dU
129 };
130
131 static unsigned long partial_crc32_one(unsigned char c, unsigned long crc)
132 {
133 return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
134 }
135
136 static unsigned long partial_crc32(const char *s, unsigned long crc)
137 {
138 while (*s)
139 crc = partial_crc32_one(*s++, crc);
140 return crc;
141 }
142
143 static unsigned long crc32(const char *s)
144 {
145 return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
146 }
147
148 /*----------------------------------------------------------------------*/
149
150 static enum symbol_type map_to_ns(enum symbol_type t)
151 {
152 switch (t) {
153 case SYM_ENUM_CONST:
154 case SYM_NORMAL:
155 case SYM_TYPEDEF:
156 return SYM_NORMAL;
157 case SYM_ENUM:
158 case SYM_STRUCT:
159 case SYM_UNION:
160 return SYM_STRUCT;
161 }
162 return t;
163 }
164
165 struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact)
166 {
167 unsigned long h = crc32(name) % HASH_BUCKETS;
168 struct symbol *sym;
169
170 for (sym = symtab[h]; sym; sym = sym->hash_next)
171 if (map_to_ns(sym->type) == map_to_ns(ns) &&
172 strcmp(name, sym->name) == 0 &&
173 sym->is_declared)
174 break;
175
176 if (exact && sym && sym->type != ns)
177 return NULL;
178 return sym;
179 }
180
181 static int is_unknown_symbol(struct symbol *sym)
182 {
183 struct string_list *defn;
184
185 return ((sym->type == SYM_STRUCT ||
186 sym->type == SYM_UNION ||
187 sym->type == SYM_ENUM) &&
188 (defn = sym->defn) && defn->tag == SYM_NORMAL &&
189 strcmp(defn->string, "}") == 0 &&
190 (defn = defn->next) && defn->tag == SYM_NORMAL &&
191 strcmp(defn->string, "UNKNOWN") == 0 &&
192 (defn = defn->next) && defn->tag == SYM_NORMAL &&
193 strcmp(defn->string, "{") == 0);
194 }
195
196 static struct symbol *__add_symbol(const char *name, enum symbol_type type,
197 struct string_list *defn, int is_extern,
198 int is_reference)
199 {
200 unsigned long h;
201 struct symbol *sym;
202 enum symbol_status status = STATUS_UNCHANGED;
203 /* The parser adds symbols in the order their declaration completes,
204 * so it is safe to store the value of the previous enum constant in
205 * a static variable.
206 */
207 static int enum_counter;
208 static struct string_list *last_enum_expr;
209
210 if (type == SYM_ENUM_CONST) {
211 if (defn) {
212 free_list(last_enum_expr, NULL);
213 last_enum_expr = copy_list_range(defn, NULL);
214 enum_counter = 1;
215 } else {
216 struct string_list *expr;
217 char buf[20];
218
219 snprintf(buf, sizeof(buf), "%d", enum_counter++);
220 if (last_enum_expr) {
221 expr = copy_list_range(last_enum_expr, NULL);
222 defn = concat_list(mk_node("("),
223 expr,
224 mk_node(")"),
225 mk_node("+"),
226 mk_node(buf), NULL);
227 } else {
228 defn = mk_node(buf);
229 }
230 }
231 } else if (type == SYM_ENUM) {
232 free_list(last_enum_expr, NULL);
233 last_enum_expr = NULL;
234 enum_counter = 0;
235 if (!name)
236 /* Anonymous enum definition, nothing more to do */
237 return NULL;
238 }
239
240 h = crc32(name) % HASH_BUCKETS;
241 for (sym = symtab[h]; sym; sym = sym->hash_next) {
242 if (map_to_ns(sym->type) == map_to_ns(type) &&
243 strcmp(name, sym->name) == 0) {
244 if (is_reference)
245 /* fall through */ ;
246 else if (sym->type == type &&
247 equal_list(sym->defn, defn)) {
248 if (!sym->is_declared && sym->is_override) {
249 print_location();
250 print_type_name(type, name);
251 fprintf(stderr, " modversion is "
252 "unchanged\n");
253 }
254 sym->is_declared = 1;
255 return sym;
256 } else if (!sym->is_declared) {
257 if (sym->is_override && flag_preserve) {
258 print_location();
259 fprintf(stderr, "ignoring ");
260 print_type_name(type, name);
261 fprintf(stderr, " modversion change\n");
262 sym->is_declared = 1;
263 return sym;
264 } else {
265 status = is_unknown_symbol(sym) ?
266 STATUS_DEFINED : STATUS_MODIFIED;
267 }
268 } else {
269 error_with_pos("redefinition of %s", name);
270 return sym;
271 }
272 break;
273 }
274 }
275
276 if (sym) {
277 struct symbol **psym;
278
279 for (psym = &symtab[h]; *psym; psym = &(*psym)->hash_next) {
280 if (*psym == sym) {
281 *psym = sym->hash_next;
282 break;
283 }
284 }
285 --nsyms;
286 }
287
288 sym = xmalloc(sizeof(*sym));
289 sym->name = name;
290 sym->type = type;
291 sym->defn = defn;
292 sym->expansion_trail = NULL;
293 sym->visited = NULL;
294 sym->is_extern = is_extern;
295
296 sym->hash_next = symtab[h];
297 symtab[h] = sym;
298
299 sym->is_declared = !is_reference;
300 sym->status = status;
301 sym->is_override = 0;
302
303 if (flag_debug) {
304 if (symbol_types[type].name)
305 fprintf(debugfile, "Defn for %s %s == <",
306 symbol_types[type].name, name);
307 else
308 fprintf(debugfile, "Defn for type%d %s == <",
309 type, name);
310 if (is_extern)
311 fputs("extern ", debugfile);
312 print_list(debugfile, defn);
313 fputs(">\n", debugfile);
314 }
315
316 ++nsyms;
317 return sym;
318 }
319
320 struct symbol *add_symbol(const char *name, enum symbol_type type,
321 struct string_list *defn, int is_extern)
322 {
323 return __add_symbol(name, type, defn, is_extern, 0);
324 }
325
326 static struct symbol *add_reference_symbol(const char *name, enum symbol_type type,
327 struct string_list *defn, int is_extern)
328 {
329 return __add_symbol(name, type, defn, is_extern, 1);
330 }
331
332 /*----------------------------------------------------------------------*/
333
334 void free_node(struct string_list *node)
335 {
336 free(node->string);
337 free(node);
338 }
339
340 void free_list(struct string_list *s, struct string_list *e)
341 {
342 while (s != e) {
343 struct string_list *next = s->next;
344 free_node(s);
345 s = next;
346 }
347 }
348
349 static struct string_list *mk_node(const char *string)
350 {
351 struct string_list *newnode;
352
353 newnode = xmalloc(sizeof(*newnode));
354 newnode->string = xstrdup(string);
355 newnode->tag = SYM_NORMAL;
356 newnode->next = NULL;
357
358 return newnode;
359 }
360
361 static struct string_list *concat_list(struct string_list *start, ...)
362 {
363 va_list ap;
364 struct string_list *n, *n2;
365
366 if (!start)
367 return NULL;
368 for (va_start(ap, start); (n = va_arg(ap, struct string_list *));) {
369 for (n2 = n; n2->next; n2 = n2->next)
370 ;
371 n2->next = start;
372 start = n;
373 }
374 va_end(ap);
375 return start;
376 }
377
378 struct string_list *copy_node(struct string_list *node)
379 {
380 struct string_list *newnode;
381
382 newnode = xmalloc(sizeof(*newnode));
383 newnode->string = xstrdup(node->string);
384 newnode->tag = node->tag;
385
386 return newnode;
387 }
388
389 struct string_list *copy_list_range(struct string_list *start,
390 struct string_list *end)
391 {
392 struct string_list *res, *n;
393
394 if (start == end)
395 return NULL;
396 n = res = copy_node(start);
397 for (start = start->next; start != end; start = start->next) {
398 n->next = copy_node(start);
399 n = n->next;
400 }
401 n->next = NULL;
402 return res;
403 }
404
405 static int equal_list(struct string_list *a, struct string_list *b)
406 {
407 while (a && b) {
408 if (a->tag != b->tag || strcmp(a->string, b->string))
409 return 0;
410 a = a->next;
411 b = b->next;
412 }
413
414 return !a && !b;
415 }
416
417 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
418
419 static struct string_list *read_node(FILE *f)
420 {
421 char buffer[256];
422 struct string_list node = {
423 .string = buffer,
424 .tag = SYM_NORMAL };
425 int c, in_string = 0;
426
427 while ((c = fgetc(f)) != EOF) {
428 if (!in_string && c == ' ') {
429 if (node.string == buffer)
430 continue;
431 break;
432 } else if (c == '"') {
433 in_string = !in_string;
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
467 static 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
503 static 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
512 static 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
541 static 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
645 void 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(!flag_rel_crcs ? "__crc_%s = 0x%08lx;\n" :
696 "SECTIONS { .rodata : ALIGN(4) { "
697 "__crc_%s = .; LONG(0x%08lx); } }\n",
698 name, crc);
699 }
700 }
701
702 /*----------------------------------------------------------------------*/
703
704 static void print_location(void)
705 {
706 fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line);
707 }
708
709 static void print_type_name(enum symbol_type type, const char *name)
710 {
711 if (symbol_types[type].name)
712 fprintf(stderr, "%s %s", symbol_types[type].name, name);
713 else
714 fprintf(stderr, "%s", name);
715 }
716
717 void error_with_pos(const char *fmt, ...)
718 {
719 va_list args;
720
721 if (flag_warnings) {
722 print_location();
723
724 va_start(args, fmt);
725 vfprintf(stderr, fmt, args);
726 va_end(args);
727 putc('\n', stderr);
728
729 errors++;
730 }
731 }
732
733 static void genksyms_usage(void)
734 {
735 fputs("Usage:\n" "genksyms [-adDTwqhVR] > /path/to/.tmp_obj.ver\n" "\n"
736 #ifdef __GNU_LIBRARY__
737 " -s, --symbol-prefix Select symbol prefix\n"
738 " -d, --debug Increment the debug level (repeatable)\n"
739 " -D, --dump Dump expanded symbol defs (for debugging only)\n"
740 " -r, --reference file Read reference symbols from a file\n"
741 " -T, --dump-types file Dump expanded types into file\n"
742 " -p, --preserve Preserve reference modversions or fail\n"
743 " -w, --warnings Enable warnings\n"
744 " -q, --quiet Disable warnings (default)\n"
745 " -h, --help Print this message\n"
746 " -V, --version Print the release version\n"
747 " -R, --relative-crc Emit section relative symbol CRCs\n"
748 #else /* __GNU_LIBRARY__ */
749 " -s Select symbol prefix\n"
750 " -d Increment the debug level (repeatable)\n"
751 " -D Dump expanded symbol defs (for debugging only)\n"
752 " -r file Read reference symbols from a file\n"
753 " -T file Dump expanded types into file\n"
754 " -p Preserve reference modversions or fail\n"
755 " -w Enable warnings\n"
756 " -q Disable warnings (default)\n"
757 " -h Print this message\n"
758 " -V Print the release version\n"
759 " -R Emit section relative symbol CRCs\n"
760 #endif /* __GNU_LIBRARY__ */
761 , stderr);
762 }
763
764 int main(int argc, char **argv)
765 {
766 FILE *dumpfile = NULL, *ref_file = NULL;
767 int o;
768
769 #ifdef __GNU_LIBRARY__
770 struct option long_opts[] = {
771 {"debug", 0, 0, 'd'},
772 {"warnings", 0, 0, 'w'},
773 {"quiet", 0, 0, 'q'},
774 {"dump", 0, 0, 'D'},
775 {"reference", 1, 0, 'r'},
776 {"dump-types", 1, 0, 'T'},
777 {"preserve", 0, 0, 'p'},
778 {"version", 0, 0, 'V'},
779 {"help", 0, 0, 'h'},
780 {"relative-crc", 0, 0, 'R'},
781 {0, 0, 0, 0}
782 };
783
784 while ((o = getopt_long(argc, argv, "s:dwqVDr:T:phR",
785 &long_opts[0], NULL)) != EOF)
786 #else /* __GNU_LIBRARY__ */
787 while ((o = getopt(argc, argv, "s:dwqVDr:T:phR")) != EOF)
788 #endif /* __GNU_LIBRARY__ */
789 switch (o) {
790 case 'd':
791 flag_debug++;
792 break;
793 case 'w':
794 flag_warnings = 1;
795 break;
796 case 'q':
797 flag_warnings = 0;
798 break;
799 case 'V':
800 fputs("genksyms version 2.5.60\n", stderr);
801 break;
802 case 'D':
803 flag_dump_defs = 1;
804 break;
805 case 'r':
806 flag_reference = 1;
807 ref_file = fopen(optarg, "r");
808 if (!ref_file) {
809 perror(optarg);
810 return 1;
811 }
812 break;
813 case 'T':
814 flag_dump_types = 1;
815 dumpfile = fopen(optarg, "w");
816 if (!dumpfile) {
817 perror(optarg);
818 return 1;
819 }
820 break;
821 case 'p':
822 flag_preserve = 1;
823 break;
824 case 'h':
825 genksyms_usage();
826 return 0;
827 case 'R':
828 flag_rel_crcs = 1;
829 break;
830 default:
831 genksyms_usage();
832 return 1;
833 }
834 {
835 extern int yydebug;
836 extern int yy_flex_debug;
837
838 yydebug = (flag_debug > 1);
839 yy_flex_debug = (flag_debug > 2);
840
841 debugfile = stderr;
842 /* setlinebuf(debugfile); */
843 }
844
845 if (flag_reference) {
846 read_reference(ref_file);
847 fclose(ref_file);
848 }
849
850 yyparse();
851
852 if (flag_dump_types && visited_symbols) {
853 while (visited_symbols != (struct symbol *)-1L) {
854 struct symbol *sym = visited_symbols;
855
856 if (sym->is_override)
857 fputs("override ", dumpfile);
858 if (symbol_types[sym->type].n) {
859 putc(symbol_types[sym->type].n, dumpfile);
860 putc('#', dumpfile);
861 }
862 fputs(sym->name, dumpfile);
863 putc(' ', dumpfile);
864 if (sym->is_extern)
865 fputs("extern ", dumpfile);
866 print_list(dumpfile, sym->defn);
867 putc('\n', dumpfile);
868
869 visited_symbols = sym->visited;
870 sym->visited = NULL;
871 }
872 }
873
874 if (flag_debug) {
875 fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
876 nsyms, HASH_BUCKETS,
877 (double)nsyms / (double)HASH_BUCKETS);
878 }
879
880 if (dumpfile)
881 fclose(dumpfile);
882
883 return errors != 0;
884 }