diff options
Diffstat (limited to 'scripts/genksyms/genksyms.c')
-rw-r--r-- | scripts/genksyms/genksyms.c | 277 |
1 files changed, 258 insertions, 19 deletions
diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c index c249274e005a..f8bb4cabd62d 100644 --- a/scripts/genksyms/genksyms.c +++ b/scripts/genksyms/genksyms.c | |||
@@ -42,7 +42,8 @@ static FILE *debugfile; | |||
42 | int cur_line = 1; | 42 | int cur_line = 1; |
43 | char *cur_filename; | 43 | char *cur_filename; |
44 | 44 | ||
45 | static int flag_debug, flag_dump_defs, flag_dump_types, flag_warnings; | 45 | static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types, |
46 | flag_preserve, flag_warnings, flag_asm; | ||
46 | static const char *arch = ""; | 47 | static const char *arch = ""; |
47 | static const char *mod_prefix = ""; | 48 | static const char *mod_prefix = ""; |
48 | 49 | ||
@@ -58,6 +59,8 @@ static const char *const symbol_type_name[] = { | |||
58 | 59 | ||
59 | static int equal_list(struct string_list *a, struct string_list *b); | 60 | static int equal_list(struct string_list *a, struct string_list *b); |
60 | static void print_list(FILE * f, struct string_list *list); | 61 | static void print_list(FILE * f, struct string_list *list); |
62 | static void print_location(void); | ||
63 | static void print_type_name(enum symbol_type type, const char *name); | ||
61 | 64 | ||
62 | /*----------------------------------------------------------------------*/ | 65 | /*----------------------------------------------------------------------*/ |
63 | 66 | ||
@@ -151,27 +154,83 @@ struct symbol *find_symbol(const char *name, enum symbol_type ns) | |||
151 | 154 | ||
152 | for (sym = symtab[h]; sym; sym = sym->hash_next) | 155 | for (sym = symtab[h]; sym; sym = sym->hash_next) |
153 | if (map_to_ns(sym->type) == map_to_ns(ns) && | 156 | if (map_to_ns(sym->type) == map_to_ns(ns) && |
154 | strcmp(name, sym->name) == 0) | 157 | strcmp(name, sym->name) == 0 && |
158 | sym->is_declared) | ||
155 | break; | 159 | break; |
156 | 160 | ||
157 | return sym; | 161 | return sym; |
158 | } | 162 | } |
159 | 163 | ||
160 | struct symbol *add_symbol(const char *name, enum symbol_type type, | 164 | static int is_unknown_symbol(struct symbol *sym) |
161 | struct string_list *defn, int is_extern) | 165 | { |
166 | struct string_list *defn; | ||
167 | |||
168 | return ((sym->type == SYM_STRUCT || | ||
169 | sym->type == SYM_UNION || | ||
170 | sym->type == SYM_ENUM) && | ||
171 | (defn = sym->defn) && defn->tag == SYM_NORMAL && | ||
172 | strcmp(defn->string, "}") == 0 && | ||
173 | (defn = defn->next) && defn->tag == SYM_NORMAL && | ||
174 | strcmp(defn->string, "UNKNOWN") == 0 && | ||
175 | (defn = defn->next) && defn->tag == SYM_NORMAL && | ||
176 | strcmp(defn->string, "{") == 0); | ||
177 | } | ||
178 | |||
179 | struct symbol *__add_symbol(const char *name, enum symbol_type type, | ||
180 | struct string_list *defn, int is_extern, | ||
181 | int is_reference) | ||
162 | { | 182 | { |
163 | unsigned long h = crc32(name) % HASH_BUCKETS; | 183 | unsigned long h = crc32(name) % HASH_BUCKETS; |
164 | struct symbol *sym; | 184 | struct symbol *sym; |
185 | enum symbol_status status = STATUS_UNCHANGED; | ||
165 | 186 | ||
166 | for (sym = symtab[h]; sym; sym = sym->hash_next) { | 187 | for (sym = symtab[h]; sym; sym = sym->hash_next) { |
167 | if (map_to_ns(sym->type) == map_to_ns(type) | 188 | if (map_to_ns(sym->type) == map_to_ns(type) && |
168 | && strcmp(name, sym->name) == 0) { | 189 | strcmp(name, sym->name) == 0) { |
169 | if (!equal_list(sym->defn, defn)) | 190 | if (is_reference) |
191 | /* fall through */ ; | ||
192 | else if (sym->type == type && | ||
193 | equal_list(sym->defn, defn)) { | ||
194 | if (!sym->is_declared && sym->is_override) { | ||
195 | print_location(); | ||
196 | print_type_name(type, name); | ||
197 | fprintf(stderr, " modversion is " | ||
198 | "unchanged\n"); | ||
199 | } | ||
200 | sym->is_declared = 1; | ||
201 | return sym; | ||
202 | } else if (!sym->is_declared) { | ||
203 | if (sym->is_override && flag_preserve) { | ||
204 | print_location(); | ||
205 | fprintf(stderr, "ignoring "); | ||
206 | print_type_name(type, name); | ||
207 | fprintf(stderr, " modversion change\n"); | ||
208 | sym->is_declared = 1; | ||
209 | return sym; | ||
210 | } else { | ||
211 | status = is_unknown_symbol(sym) ? | ||
212 | STATUS_DEFINED : STATUS_MODIFIED; | ||
213 | } | ||
214 | } else { | ||
170 | error_with_pos("redefinition of %s", name); | 215 | error_with_pos("redefinition of %s", name); |
171 | return sym; | 216 | return sym; |
217 | } | ||
218 | break; | ||
172 | } | 219 | } |
173 | } | 220 | } |
174 | 221 | ||
222 | if (sym) { | ||
223 | struct symbol **psym; | ||
224 | |||
225 | for (psym = &symtab[h]; *psym; psym = &(*psym)->hash_next) { | ||
226 | if (*psym == sym) { | ||
227 | *psym = sym->hash_next; | ||
228 | break; | ||
229 | } | ||
230 | } | ||
231 | --nsyms; | ||
232 | } | ||
233 | |||
175 | sym = xmalloc(sizeof(*sym)); | 234 | sym = xmalloc(sizeof(*sym)); |
176 | sym->name = name; | 235 | sym->name = name; |
177 | sym->type = type; | 236 | sym->type = type; |
@@ -183,6 +242,10 @@ struct symbol *add_symbol(const char *name, enum symbol_type type, | |||
183 | sym->hash_next = symtab[h]; | 242 | sym->hash_next = symtab[h]; |
184 | symtab[h] = sym; | 243 | symtab[h] = sym; |
185 | 244 | ||
245 | sym->is_declared = !is_reference; | ||
246 | sym->status = status; | ||
247 | sym->is_override = 0; | ||
248 | |||
186 | if (flag_debug) { | 249 | if (flag_debug) { |
187 | fprintf(debugfile, "Defn for %s %s == <", | 250 | fprintf(debugfile, "Defn for %s %s == <", |
188 | symbol_type_name[type], name); | 251 | symbol_type_name[type], name); |
@@ -196,6 +259,18 @@ struct symbol *add_symbol(const char *name, enum symbol_type type, | |||
196 | return sym; | 259 | return sym; |
197 | } | 260 | } |
198 | 261 | ||
262 | struct symbol *add_symbol(const char *name, enum symbol_type type, | ||
263 | struct string_list *defn, int is_extern) | ||
264 | { | ||
265 | return __add_symbol(name, type, defn, is_extern, 0); | ||
266 | } | ||
267 | |||
268 | struct symbol *add_reference_symbol(const char *name, enum symbol_type type, | ||
269 | struct string_list *defn, int is_extern) | ||
270 | { | ||
271 | return __add_symbol(name, type, defn, is_extern, 1); | ||
272 | } | ||
273 | |||
199 | /*----------------------------------------------------------------------*/ | 274 | /*----------------------------------------------------------------------*/ |
200 | 275 | ||
201 | void free_node(struct string_list *node) | 276 | void free_node(struct string_list *node) |
@@ -236,6 +311,90 @@ static int equal_list(struct string_list *a, struct string_list *b) | |||
236 | return !a && !b; | 311 | return !a && !b; |
237 | } | 312 | } |
238 | 313 | ||
314 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) | ||
315 | |||
316 | struct string_list *read_node(FILE *f) | ||
317 | { | ||
318 | char buffer[256]; | ||
319 | struct string_list node = { | ||
320 | .string = buffer, | ||
321 | .tag = SYM_NORMAL }; | ||
322 | int c; | ||
323 | |||
324 | while ((c = fgetc(f)) != EOF) { | ||
325 | if (c == ' ') { | ||
326 | if (node.string == buffer) | ||
327 | continue; | ||
328 | break; | ||
329 | } else if (c == '\n') { | ||
330 | if (node.string == buffer) | ||
331 | return NULL; | ||
332 | ungetc(c, f); | ||
333 | break; | ||
334 | } | ||
335 | if (node.string >= buffer + sizeof(buffer) - 1) { | ||
336 | fprintf(stderr, "Token too long\n"); | ||
337 | exit(1); | ||
338 | } | ||
339 | *node.string++ = c; | ||
340 | } | ||
341 | if (node.string == buffer) | ||
342 | return NULL; | ||
343 | *node.string = 0; | ||
344 | node.string = buffer; | ||
345 | |||
346 | if (node.string[1] == '#') { | ||
347 | int n; | ||
348 | |||
349 | for (n = 0; n < ARRAY_SIZE(symbol_type_name); n++) { | ||
350 | if (node.string[0] == symbol_type_name[n][0]) { | ||
351 | node.tag = n; | ||
352 | node.string += 2; | ||
353 | return copy_node(&node); | ||
354 | } | ||
355 | } | ||
356 | fprintf(stderr, "Unknown type %c\n", node.string[0]); | ||
357 | exit(1); | ||
358 | } | ||
359 | return copy_node(&node); | ||
360 | } | ||
361 | |||
362 | static void read_reference(FILE *f) | ||
363 | { | ||
364 | while (!feof(f)) { | ||
365 | struct string_list *defn = NULL; | ||
366 | struct string_list *sym, *def; | ||
367 | int is_extern = 0, is_override = 0; | ||
368 | struct symbol *subsym; | ||
369 | |||
370 | sym = read_node(f); | ||
371 | if (sym && sym->tag == SYM_NORMAL && | ||
372 | !strcmp(sym->string, "override")) { | ||
373 | is_override = 1; | ||
374 | free_node(sym); | ||
375 | sym = read_node(f); | ||
376 | } | ||
377 | if (!sym) | ||
378 | continue; | ||
379 | def = read_node(f); | ||
380 | if (def && def->tag == SYM_NORMAL && | ||
381 | !strcmp(def->string, "extern")) { | ||
382 | is_extern = 1; | ||
383 | free_node(def); | ||
384 | def = read_node(f); | ||
385 | } | ||
386 | while (def) { | ||
387 | def->next = defn; | ||
388 | defn = def; | ||
389 | def = read_node(f); | ||
390 | } | ||
391 | subsym = add_reference_symbol(xstrdup(sym->string), sym->tag, | ||
392 | defn, is_extern); | ||
393 | subsym->is_override = is_override; | ||
394 | free_node(sym); | ||
395 | } | ||
396 | } | ||
397 | |||
239 | static void print_node(FILE * f, struct string_list *list) | 398 | static void print_node(FILE * f, struct string_list *list) |
240 | { | 399 | { |
241 | if (list->tag != SYM_NORMAL) { | 400 | if (list->tag != SYM_NORMAL) { |
@@ -311,6 +470,7 @@ static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc) | |||
311 | 470 | ||
312 | case SYM_TYPEDEF: | 471 | case SYM_TYPEDEF: |
313 | subsym = find_symbol(cur->string, cur->tag); | 472 | subsym = find_symbol(cur->string, cur->tag); |
473 | /* FIXME: Bad reference files can segfault here. */ | ||
314 | if (subsym->expansion_trail) { | 474 | if (subsym->expansion_trail) { |
315 | if (flag_dump_defs) | 475 | if (flag_dump_defs) |
316 | fprintf(debugfile, "%s ", cur->string); | 476 | fprintf(debugfile, "%s ", cur->string); |
@@ -347,9 +507,22 @@ static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc) | |||
347 | t = n; | 507 | t = n; |
348 | 508 | ||
349 | n = xmalloc(sizeof(*n)); | 509 | n = xmalloc(sizeof(*n)); |
350 | n->string = xstrdup("{ UNKNOWN }"); | 510 | n->string = xstrdup("{"); |
511 | n->tag = SYM_NORMAL; | ||
512 | n->next = t; | ||
513 | t = n; | ||
514 | |||
515 | n = xmalloc(sizeof(*n)); | ||
516 | n->string = xstrdup("UNKNOWN"); | ||
517 | n->tag = SYM_NORMAL; | ||
518 | n->next = t; | ||
519 | t = n; | ||
520 | |||
521 | n = xmalloc(sizeof(*n)); | ||
522 | n->string = xstrdup("}"); | ||
351 | n->tag = SYM_NORMAL; | 523 | n->tag = SYM_NORMAL; |
352 | n->next = t; | 524 | n->next = t; |
525 | t = n; | ||
353 | 526 | ||
354 | subsym = | 527 | subsym = |
355 | add_symbol(cur->string, cur->tag, n, 0); | 528 | add_symbol(cur->string, cur->tag, n, 0); |
@@ -397,37 +570,75 @@ void export_symbol(const char *name) | |||
397 | error_with_pos("export undefined symbol %s", name); | 570 | error_with_pos("export undefined symbol %s", name); |
398 | else { | 571 | else { |
399 | unsigned long crc; | 572 | unsigned long crc; |
573 | int has_changed = 0; | ||
400 | 574 | ||
401 | if (flag_dump_defs) | 575 | if (flag_dump_defs) |
402 | fprintf(debugfile, "Export %s == <", name); | 576 | fprintf(debugfile, "Export %s == <", name); |
403 | 577 | ||
404 | expansion_trail = (struct symbol *)-1L; | 578 | expansion_trail = (struct symbol *)-1L; |
405 | 579 | ||
580 | sym->expansion_trail = expansion_trail; | ||
581 | expansion_trail = sym; | ||
406 | crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff; | 582 | crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff; |
407 | 583 | ||
408 | sym = expansion_trail; | 584 | sym = expansion_trail; |
409 | while (sym != (struct symbol *)-1L) { | 585 | while (sym != (struct symbol *)-1L) { |
410 | struct symbol *n = sym->expansion_trail; | 586 | struct symbol *n = sym->expansion_trail; |
587 | |||
588 | if (sym->status != STATUS_UNCHANGED) { | ||
589 | if (!has_changed) { | ||
590 | print_location(); | ||
591 | fprintf(stderr, "%s: %s: modversion " | ||
592 | "changed because of changes " | ||
593 | "in ", flag_preserve ? "error" : | ||
594 | "warning", name); | ||
595 | } else | ||
596 | fprintf(stderr, ", "); | ||
597 | print_type_name(sym->type, sym->name); | ||
598 | if (sym->status == STATUS_DEFINED) | ||
599 | fprintf(stderr, " (became defined)"); | ||
600 | has_changed = 1; | ||
601 | if (flag_preserve) | ||
602 | errors++; | ||
603 | } | ||
411 | sym->expansion_trail = 0; | 604 | sym->expansion_trail = 0; |
412 | sym = n; | 605 | sym = n; |
413 | } | 606 | } |
607 | if (has_changed) | ||
608 | fprintf(stderr, "\n"); | ||
414 | 609 | ||
415 | if (flag_dump_defs) | 610 | if (flag_dump_defs) |
416 | fputs(">\n", debugfile); | 611 | fputs(">\n", debugfile); |
417 | 612 | ||
418 | /* Used as a linker script. */ | 613 | /* Used as assembly source or a linker script. */ |
419 | printf("%s__crc_%s = 0x%08lx ;\n", mod_prefix, name, crc); | 614 | printf(flag_asm |
615 | ? ".equiv %s__crc_%s, %#08lx\n" | ||
616 | : "%s__crc_%s = %#08lx ;\n", | ||
617 | mod_prefix, name, crc); | ||
420 | } | 618 | } |
421 | } | 619 | } |
422 | 620 | ||
423 | /*----------------------------------------------------------------------*/ | 621 | /*----------------------------------------------------------------------*/ |
622 | |||
623 | static void print_location(void) | ||
624 | { | ||
625 | fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line); | ||
626 | } | ||
627 | |||
628 | static void print_type_name(enum symbol_type type, const char *name) | ||
629 | { | ||
630 | if (type != SYM_NORMAL) | ||
631 | fprintf(stderr, "%s %s", symbol_type_name[type], name); | ||
632 | else | ||
633 | fprintf(stderr, "%s", name); | ||
634 | } | ||
635 | |||
424 | void error_with_pos(const char *fmt, ...) | 636 | void error_with_pos(const char *fmt, ...) |
425 | { | 637 | { |
426 | va_list args; | 638 | va_list args; |
427 | 639 | ||
428 | if (flag_warnings) { | 640 | if (flag_warnings) { |
429 | fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", | 641 | print_location(); |
430 | cur_line); | ||
431 | 642 | ||
432 | va_start(args, fmt); | 643 | va_start(args, fmt); |
433 | vfprintf(stderr, fmt, args); | 644 | vfprintf(stderr, fmt, args); |
@@ -440,21 +651,27 @@ void error_with_pos(const char *fmt, ...) | |||
440 | 651 | ||
441 | static void genksyms_usage(void) | 652 | static void genksyms_usage(void) |
442 | { | 653 | { |
443 | fputs("Usage:\n" "genksyms [-adDTwqhV] > /path/to/.tmp_obj.ver\n" "\n" | 654 | fputs("Usage:\n" "genksyms [-aAdDTwqhV] > /path/to/.tmp_obj.ver\n" "\n" |
444 | #ifdef __GNU_LIBRARY__ | 655 | #ifdef __GNU_LIBRARY__ |
445 | " -a, --arch Select architecture\n" | 656 | " -a, --arch Select architecture\n" |
657 | " -A, --asm Generate assembly rather than linker script\n" | ||
446 | " -d, --debug Increment the debug level (repeatable)\n" | 658 | " -d, --debug Increment the debug level (repeatable)\n" |
447 | " -D, --dump Dump expanded symbol defs (for debugging only)\n" | 659 | " -D, --dump Dump expanded symbol defs (for debugging only)\n" |
448 | " -T, --dump-types file Dump expanded types into file (for debugging only)\n" | 660 | " -r, --reference file Read reference symbols from a file\n" |
661 | " -T, --dump-types file Dump expanded types into file\n" | ||
662 | " -p, --preserve Preserve reference modversions or fail\n" | ||
449 | " -w, --warnings Enable warnings\n" | 663 | " -w, --warnings Enable warnings\n" |
450 | " -q, --quiet Disable warnings (default)\n" | 664 | " -q, --quiet Disable warnings (default)\n" |
451 | " -h, --help Print this message\n" | 665 | " -h, --help Print this message\n" |
452 | " -V, --version Print the release version\n" | 666 | " -V, --version Print the release version\n" |
453 | #else /* __GNU_LIBRARY__ */ | 667 | #else /* __GNU_LIBRARY__ */ |
454 | " -a Select architecture\n" | 668 | " -a Select architecture\n" |
669 | " -A Generate assembly rather than linker script\n" | ||
455 | " -d Increment the debug level (repeatable)\n" | 670 | " -d Increment the debug level (repeatable)\n" |
456 | " -D Dump expanded symbol defs (for debugging only)\n" | 671 | " -D Dump expanded symbol defs (for debugging only)\n" |
457 | " -T file Dump expanded types into file (for debugging only)\n" | 672 | " -r file Read reference symbols from a file\n" |
673 | " -T file Dump expanded types into file\n" | ||
674 | " -p Preserve reference modversions or fail\n" | ||
458 | " -w Enable warnings\n" | 675 | " -w Enable warnings\n" |
459 | " -q Disable warnings (default)\n" | 676 | " -q Disable warnings (default)\n" |
460 | " -h Print this message\n" | 677 | " -h Print this message\n" |
@@ -465,26 +682,29 @@ static void genksyms_usage(void) | |||
465 | 682 | ||
466 | int main(int argc, char **argv) | 683 | int main(int argc, char **argv) |
467 | { | 684 | { |
468 | FILE *dumpfile = NULL; | 685 | FILE *dumpfile = NULL, *ref_file = NULL; |
469 | int o; | 686 | int o; |
470 | 687 | ||
471 | #ifdef __GNU_LIBRARY__ | 688 | #ifdef __GNU_LIBRARY__ |
472 | struct option long_opts[] = { | 689 | struct option long_opts[] = { |
473 | {"arch", 1, 0, 'a'}, | 690 | {"arch", 1, 0, 'a'}, |
691 | {"asm", 0, 0, 'A'}, | ||
474 | {"debug", 0, 0, 'd'}, | 692 | {"debug", 0, 0, 'd'}, |
475 | {"warnings", 0, 0, 'w'}, | 693 | {"warnings", 0, 0, 'w'}, |
476 | {"quiet", 0, 0, 'q'}, | 694 | {"quiet", 0, 0, 'q'}, |
477 | {"dump", 0, 0, 'D'}, | 695 | {"dump", 0, 0, 'D'}, |
696 | {"reference", 1, 0, 'r'}, | ||
478 | {"dump-types", 1, 0, 'T'}, | 697 | {"dump-types", 1, 0, 'T'}, |
698 | {"preserve", 0, 0, 'p'}, | ||
479 | {"version", 0, 0, 'V'}, | 699 | {"version", 0, 0, 'V'}, |
480 | {"help", 0, 0, 'h'}, | 700 | {"help", 0, 0, 'h'}, |
481 | {0, 0, 0, 0} | 701 | {0, 0, 0, 0} |
482 | }; | 702 | }; |
483 | 703 | ||
484 | while ((o = getopt_long(argc, argv, "a:dwqVDT:h", | 704 | while ((o = getopt_long(argc, argv, "a:dwqVADr:T:ph", |
485 | &long_opts[0], NULL)) != EOF) | 705 | &long_opts[0], NULL)) != EOF) |
486 | #else /* __GNU_LIBRARY__ */ | 706 | #else /* __GNU_LIBRARY__ */ |
487 | while ((o = getopt(argc, argv, "a:dwqVDT:h")) != EOF) | 707 | while ((o = getopt(argc, argv, "a:dwqVADr:T:ph")) != EOF) |
488 | #endif /* __GNU_LIBRARY__ */ | 708 | #endif /* __GNU_LIBRARY__ */ |
489 | switch (o) { | 709 | switch (o) { |
490 | case 'a': | 710 | case 'a': |
@@ -502,9 +722,20 @@ int main(int argc, char **argv) | |||
502 | case 'V': | 722 | case 'V': |
503 | fputs("genksyms version 2.5.60\n", stderr); | 723 | fputs("genksyms version 2.5.60\n", stderr); |
504 | break; | 724 | break; |
725 | case 'A': | ||
726 | flag_asm = 1; | ||
727 | break; | ||
505 | case 'D': | 728 | case 'D': |
506 | flag_dump_defs = 1; | 729 | flag_dump_defs = 1; |
507 | break; | 730 | break; |
731 | case 'r': | ||
732 | flag_reference = 1; | ||
733 | ref_file = fopen(optarg, "r"); | ||
734 | if (!ref_file) { | ||
735 | perror(optarg); | ||
736 | return 1; | ||
737 | } | ||
738 | break; | ||
508 | case 'T': | 739 | case 'T': |
509 | flag_dump_types = 1; | 740 | flag_dump_types = 1; |
510 | dumpfile = fopen(optarg, "w"); | 741 | dumpfile = fopen(optarg, "w"); |
@@ -513,6 +744,9 @@ int main(int argc, char **argv) | |||
513 | return 1; | 744 | return 1; |
514 | } | 745 | } |
515 | break; | 746 | break; |
747 | case 'p': | ||
748 | flag_preserve = 1; | ||
749 | break; | ||
516 | case 'h': | 750 | case 'h': |
517 | genksyms_usage(); | 751 | genksyms_usage(); |
518 | return 0; | 752 | return 0; |
@@ -533,12 +767,17 @@ int main(int argc, char **argv) | |||
533 | /* setlinebuf(debugfile); */ | 767 | /* setlinebuf(debugfile); */ |
534 | } | 768 | } |
535 | 769 | ||
770 | if (flag_reference) | ||
771 | read_reference(ref_file); | ||
772 | |||
536 | yyparse(); | 773 | yyparse(); |
537 | 774 | ||
538 | if (flag_dump_types && visited_symbols) { | 775 | if (flag_dump_types && visited_symbols) { |
539 | while (visited_symbols != (struct symbol *)-1L) { | 776 | while (visited_symbols != (struct symbol *)-1L) { |
540 | struct symbol *sym = visited_symbols; | 777 | struct symbol *sym = visited_symbols; |
541 | 778 | ||
779 | if (sym->is_override) | ||
780 | fputs("override ", dumpfile); | ||
542 | if (sym->type != SYM_NORMAL) { | 781 | if (sym->type != SYM_NORMAL) { |
543 | putc(symbol_type_name[sym->type][0], dumpfile); | 782 | putc(symbol_type_name[sym->type][0], dumpfile); |
544 | putc('#', dumpfile); | 783 | putc('#', dumpfile); |