]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/tlink.c
Merge from pch-branch up to tag pch-commit-20020603.
[thirdparty/gcc.git] / gcc / tlink.c
1 /* Scan linker error messages for missing template instantiations and provide
2 them.
3
4 Copyright (C) 1995, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
5 Contributed by Jason Merrill (jason@cygnus.com).
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 2, or (at your option) any later
12 version.
13
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING. If not, write to the Free
21 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 02111-1307, USA. */
23
24 #include "config.h"
25 #include "system.h"
26 #include "intl.h"
27 #include "obstack.h"
28 #include "hashtab.h"
29 #include "demangle.h"
30 #include "collect2.h"
31
32 #define MAX_ITERATIONS 17
33
34 /* Obstack allocation and deallocation routines. */
35 #define obstack_chunk_alloc xmalloc
36 #define obstack_chunk_free free
37
38 /* Defined in the automatically-generated underscore.c. */
39 extern int prepends_underscore;
40
41 static int tlink_verbose;
42 \f
43 /* Hash table boilerplate for working with htab_t. We have hash tables
44 for symbol names, file names, and demangled symbols. */
45
46 typedef struct symbol_hash_entry
47 {
48 const char *key;
49 struct file_hash_entry *file;
50 int chosen;
51 int tweaking;
52 int tweaked;
53 } symbol;
54
55 typedef struct file_hash_entry
56 {
57 const char *key;
58 const char *args;
59 const char *dir;
60 const char *main;
61 int tweaking;
62 } file;
63
64 typedef struct demangled_hash_entry
65 {
66 const char *key;
67 const char *mangled;
68 } demangled;
69
70 /* Hash and comparison functions for these hash tables. */
71
72 static int hash_string_eq PARAMS ((const void *, const void *));
73 static hashval_t hash_string_hash PARAMS ((const void *));
74
75 static int
76 hash_string_eq (s1_p, s2_p)
77 const void *s1_p;
78 const void *s2_p;
79 {
80 const char *const *s1 = (const char *const *)s1_p;
81 const char *s2 = (const char *)s2_p;
82 return strcmp (*s1, s2) == 0;
83 }
84
85 static hashval_t
86 hash_string_hash (s_p)
87 const void *s_p;
88 {
89 const char *const *s = (const char *const *)s_p;
90 return (*htab_hash_string) (*s);
91 }
92
93 static htab_t symbol_table;
94
95 static struct symbol_hash_entry * symbol_hash_lookup PARAMS ((const char *,
96 int));
97 static struct file_hash_entry * file_hash_lookup PARAMS ((const char *));
98 static struct demangled_hash_entry *
99 demangled_hash_lookup PARAMS ((const char *, int));
100 static void symbol_push PARAMS ((symbol *));
101 static symbol * symbol_pop PARAMS ((void));
102 static void file_push PARAMS ((file *));
103 static file * file_pop PARAMS ((void));
104 static void tlink_init PARAMS ((void));
105 static int tlink_execute PARAMS ((const char *, char **, const char *));
106 static char * frob_extension PARAMS ((const char *, const char *));
107 static char * obstack_fgets PARAMS ((FILE *, struct obstack *));
108 static char * tfgets PARAMS ((FILE *));
109 static char * pfgets PARAMS ((FILE *));
110 static void freadsym PARAMS ((FILE *, file *, int));
111 static void read_repo_file PARAMS ((file *));
112 static void maybe_tweak PARAMS ((char *, file *));
113 static int recompile_files PARAMS ((void));
114 static int read_repo_files PARAMS ((char **));
115 static void demangle_new_symbols PARAMS ((void));
116 static int scan_linker_output PARAMS ((const char *));
117
118 /* Look up an entry in the symbol hash table. */
119
120 static struct symbol_hash_entry *
121 symbol_hash_lookup (string, create)
122 const char *string;
123 int create;
124 {
125 PTR *e;
126 e = htab_find_slot_with_hash (symbol_table, string,
127 (*htab_hash_string)(string),
128 create ? INSERT : NO_INSERT);
129 if (e == NULL)
130 return NULL;
131 if (*e == NULL)
132 {
133 struct symbol_hash_entry *v;
134 *e = v = xcalloc (1, sizeof (*v));
135 v->key = xstrdup (string);
136 }
137 return *e;
138 }
139
140 static htab_t file_table;
141
142 /* Look up an entry in the file hash table. */
143
144 static struct file_hash_entry *
145 file_hash_lookup (string)
146 const char *string;
147 {
148 PTR *e;
149 e = htab_find_slot_with_hash (file_table, string,
150 (*htab_hash_string)(string),
151 INSERT);
152 if (*e == NULL)
153 {
154 struct file_hash_entry *v;
155 *e = v = xcalloc (1, sizeof (*v));
156 v->key = xstrdup (string);
157 }
158 return *e;
159 }
160
161 static htab_t demangled_table;
162
163 /* Look up an entry in the demangled name hash table. */
164
165 static struct demangled_hash_entry *
166 demangled_hash_lookup (string, create)
167 const char *string;
168 int create;
169 {
170 PTR *e;
171 e = htab_find_slot_with_hash (demangled_table, string,
172 (*htab_hash_string)(string),
173 create ? INSERT : NO_INSERT);
174 if (e == NULL)
175 return NULL;
176 if (*e == NULL)
177 {
178 struct demangled_hash_entry *v;
179 *e = v = xcalloc (1, sizeof (*v));
180 v->key = xstrdup (string);
181 }
182 return *e;
183 }
184 \f
185 /* Stack code. */
186
187 struct symbol_stack_entry
188 {
189 symbol *value;
190 struct symbol_stack_entry *next;
191 };
192 struct obstack symbol_stack_obstack;
193 struct symbol_stack_entry *symbol_stack;
194
195 struct file_stack_entry
196 {
197 file *value;
198 struct file_stack_entry *next;
199 };
200 struct obstack file_stack_obstack;
201 struct file_stack_entry *file_stack;
202
203 static void
204 symbol_push (p)
205 symbol *p;
206 {
207 struct symbol_stack_entry *ep = (struct symbol_stack_entry *) obstack_alloc
208 (&symbol_stack_obstack, sizeof (struct symbol_stack_entry));
209 ep->value = p;
210 ep->next = symbol_stack;
211 symbol_stack = ep;
212 }
213
214 static symbol *
215 symbol_pop ()
216 {
217 struct symbol_stack_entry *ep = symbol_stack;
218 symbol *p;
219 if (ep == NULL)
220 return NULL;
221 p = ep->value;
222 symbol_stack = ep->next;
223 obstack_free (&symbol_stack_obstack, ep);
224 return p;
225 }
226
227 static void
228 file_push (p)
229 file *p;
230 {
231 struct file_stack_entry *ep;
232
233 if (p->tweaking)
234 return;
235
236 ep = (struct file_stack_entry *) obstack_alloc
237 (&file_stack_obstack, sizeof (struct file_stack_entry));
238 ep->value = p;
239 ep->next = file_stack;
240 file_stack = ep;
241 p->tweaking = 1;
242 }
243
244 static file *
245 file_pop ()
246 {
247 struct file_stack_entry *ep = file_stack;
248 file *p;
249 if (ep == NULL)
250 return NULL;
251 p = ep->value;
252 file_stack = ep->next;
253 obstack_free (&file_stack_obstack, ep);
254 p->tweaking = 0;
255 return p;
256 }
257 \f
258 /* Other machinery. */
259
260 /* Initialize the tlink machinery. Called from do_tlink. */
261
262 static void
263 tlink_init ()
264 {
265 const char *p;
266
267 symbol_table = htab_create (500, hash_string_hash, hash_string_eq,
268 NULL);
269 file_table = htab_create (500, hash_string_hash, hash_string_eq,
270 NULL);
271 demangled_table = htab_create (500, hash_string_hash, hash_string_eq,
272 NULL);
273
274 obstack_begin (&symbol_stack_obstack, 0);
275 obstack_begin (&file_stack_obstack, 0);
276
277 p = getenv ("TLINK_VERBOSE");
278 if (p)
279 tlink_verbose = atoi (p);
280 else
281 {
282 tlink_verbose = 1;
283 if (vflag)
284 tlink_verbose = 2;
285 if (debug)
286 tlink_verbose = 3;
287 }
288 }
289
290 static int
291 tlink_execute (prog, argv, redir)
292 const char *prog;
293 char **argv;
294 const char *redir;
295 {
296 collect_execute (prog, argv, redir);
297 return collect_wait (prog);
298 }
299
300 static char *
301 frob_extension (s, ext)
302 const char *s;
303 const char *ext;
304 {
305 const char *p = strrchr (s, '/');
306 if (! p)
307 p = s;
308 p = strrchr (p, '.');
309 if (! p)
310 p = s + strlen (s);
311
312 obstack_grow (&temporary_obstack, s, p - s);
313 return obstack_copy0 (&temporary_obstack, ext, strlen (ext));
314 }
315
316 static char *
317 obstack_fgets (stream, ob)
318 FILE *stream;
319 struct obstack *ob;
320 {
321 int c;
322 while ((c = getc (stream)) != EOF && c != '\n')
323 obstack_1grow (ob, c);
324 if (obstack_object_size (ob) == 0)
325 return NULL;
326 obstack_1grow (ob, '\0');
327 return obstack_finish (ob);
328 }
329
330 static char *
331 tfgets (stream)
332 FILE *stream;
333 {
334 return obstack_fgets (stream, &temporary_obstack);
335 }
336
337 static char *
338 pfgets (stream)
339 FILE *stream;
340 {
341 return obstack_fgets (stream, &permanent_obstack);
342 }
343 \f
344 /* Real tlink code. */
345
346 /* Subroutine of read_repo_file. We are reading the repo file for file F,
347 which is coming in on STREAM, and the symbol that comes next in STREAM
348 is offerred, chosen or provided if CHOSEN is 0, 1 or 2, respectively.
349
350 XXX "provided" is unimplemented, both here and in the compiler. */
351
352 static void
353 freadsym (stream, f, chosen)
354 FILE *stream;
355 file *f;
356 int chosen;
357 {
358 symbol *sym;
359
360 {
361 const char *name = tfgets (stream);
362 sym = symbol_hash_lookup (name, true);
363 }
364
365 if (sym->file == NULL)
366 {
367 /* We didn't have this symbol already, so we choose this file. */
368
369 symbol_push (sym);
370 sym->file = f;
371 sym->chosen = chosen;
372 }
373 else if (chosen)
374 {
375 /* We want this file; cast aside any pretender. */
376
377 if (sym->chosen && sym->file != f)
378 {
379 if (sym->chosen == 1)
380 file_push (sym->file);
381 else
382 {
383 file_push (f);
384 f = sym->file;
385 chosen = sym->chosen;
386 }
387 }
388 sym->file = f;
389 sym->chosen = chosen;
390 }
391 }
392
393 /* Read in the repo file denoted by F, and record all its information. */
394
395 static void
396 read_repo_file (f)
397 file *f;
398 {
399 char c;
400 FILE *stream = fopen (f->key, "r");
401
402 if (tlink_verbose >= 2)
403 fprintf (stderr, _("collect: reading %s\n"), f->key);
404
405 while (fscanf (stream, "%c ", &c) == 1)
406 {
407 switch (c)
408 {
409 case 'A':
410 f->args = pfgets (stream);
411 break;
412 case 'D':
413 f->dir = pfgets (stream);
414 break;
415 case 'M':
416 f->main = pfgets (stream);
417 break;
418 case 'P':
419 freadsym (stream, f, 2);
420 break;
421 case 'C':
422 freadsym (stream, f, 1);
423 break;
424 case 'O':
425 freadsym (stream, f, 0);
426 break;
427 }
428 obstack_free (&temporary_obstack, temporary_firstobj);
429 }
430 fclose (stream);
431 if (f->args == NULL)
432 f->args = getenv ("COLLECT_GCC_OPTIONS");
433 if (f->dir == NULL)
434 f->dir = ".";
435 }
436
437 /* We might want to modify LINE, which is a symbol line from file F. We do
438 this if either we saw an error message referring to the symbol in
439 question, or we have already allocated the symbol to another file and
440 this one wants to emit it as well. */
441
442 static void
443 maybe_tweak (line, f)
444 char *line;
445 file *f;
446 {
447 symbol *sym = symbol_hash_lookup (line + 2, false);
448
449 if ((sym->file == f && sym->tweaking)
450 || (sym->file != f && line[0] == 'C'))
451 {
452 sym->tweaking = 0;
453 sym->tweaked = 1;
454
455 if (line[0] == 'O')
456 line[0] = 'C';
457 else
458 line[0] = 'O';
459 }
460 }
461
462 /* Update the repo files for each of the object files we have adjusted and
463 recompile.
464
465 XXX Should this use collect_execute instead of system? */
466
467 static int
468 recompile_files ()
469 {
470 file *f;
471
472 putenv (xstrdup ("COMPILER_PATH"));
473 putenv (xstrdup ("LIBRARY_PATH"));
474
475 while ((f = file_pop ()) != NULL)
476 {
477 char *line, *command;
478 FILE *stream = fopen (f->key, "r");
479 const char *const outname = frob_extension (f->key, ".rnw");
480 FILE *output = fopen (outname, "w");
481
482 while ((line = tfgets (stream)) != NULL)
483 {
484 switch (line[0])
485 {
486 case 'C':
487 case 'O':
488 maybe_tweak (line, f);
489 }
490 fprintf (output, "%s\n", line);
491 }
492 fclose (stream);
493 fclose (output);
494 rename (outname, f->key);
495
496 obstack_grow (&temporary_obstack, "cd ", 3);
497 obstack_grow (&temporary_obstack, f->dir, strlen (f->dir));
498 obstack_grow (&temporary_obstack, "; ", 2);
499 obstack_grow (&temporary_obstack, c_file_name, strlen (c_file_name));
500 obstack_1grow (&temporary_obstack, ' ');
501 obstack_grow (&temporary_obstack, f->args, strlen (f->args));
502 obstack_1grow (&temporary_obstack, ' ');
503 command = obstack_copy0 (&temporary_obstack, f->main, strlen (f->main));
504
505 if (tlink_verbose)
506 fprintf (stderr, _("collect: recompiling %s\n"), f->main);
507 if (tlink_verbose >= 3)
508 fprintf (stderr, "%s\n", command);
509
510 if (system (command) != 0)
511 return 0;
512
513 read_repo_file (f);
514
515 obstack_free (&temporary_obstack, temporary_firstobj);
516 }
517 return 1;
518 }
519
520 /* The first phase of processing: determine which object files have
521 .rpo files associated with them, and read in the information. */
522
523 static int
524 read_repo_files (object_lst)
525 char **object_lst;
526 {
527 char **object = object_lst;
528
529 for (; *object; object++)
530 {
531 const char *p;
532 file *f;
533
534 /* Don't bother trying for ld flags. */
535 if (*object[0] == '-')
536 continue;
537
538 p = frob_extension (*object, ".rpo");
539
540 if (! file_exists (p))
541 continue;
542
543 f = file_hash_lookup (p);
544
545 read_repo_file (f);
546 }
547
548 if (file_stack != NULL && ! recompile_files ())
549 return 0;
550
551 return (symbol_stack != NULL);
552 }
553
554 /* Add the demangled forms of any new symbols to the hash table. */
555
556 static void
557 demangle_new_symbols ()
558 {
559 symbol *sym;
560
561 while ((sym = symbol_pop ()) != NULL)
562 {
563 demangled *dem;
564 const char *p = cplus_demangle (sym->key, DMGL_PARAMS | DMGL_ANSI);
565
566 if (! p)
567 continue;
568
569 dem = demangled_hash_lookup (p, true);
570 dem->mangled = sym->key;
571 }
572 }
573
574 /* Step through the output of the linker, in the file named FNAME, and
575 adjust the settings for each symbol encountered. */
576
577 static int
578 scan_linker_output (fname)
579 const char *fname;
580 {
581 FILE *stream = fopen (fname, "r");
582 char *line;
583
584 while ((line = tfgets (stream)) != NULL)
585 {
586 char *p = line, *q;
587 symbol *sym;
588 int end;
589
590 while (*p && ISSPACE ((unsigned char)*p))
591 ++p;
592
593 if (! *p)
594 continue;
595
596 for (q = p; *q && ! ISSPACE ((unsigned char)*q); ++q)
597 ;
598
599 /* Try the first word on the line. */
600 if (*p == '.')
601 ++p;
602 if (*p == '_' && prepends_underscore)
603 ++p;
604
605 end = ! *q;
606 *q = 0;
607 sym = symbol_hash_lookup (p, false);
608
609 /* Some SVR4 linkers produce messages like
610 ld: 0711-317 ERROR: Undefined symbol: .g__t3foo1Zi
611 */
612 if (! sym && ! end && strstr (q+1, "Undefined symbol: "))
613 {
614 char *p = strrchr (q+1, ' ');
615 p++;
616 if (*p == '.')
617 p++;
618 if (*p == '_' && prepends_underscore)
619 p++;
620 sym = symbol_hash_lookup (p, false);
621 }
622
623 if (! sym && ! end)
624 /* Try a mangled name in quotes. */
625 {
626 const char *oldq = q+1;
627 demangled *dem = 0;
628 q = 0;
629
630 /* First try `GNU style'. */
631 p = strchr (oldq, '`');
632 if (p)
633 p++, q = strchr (p, '\'');
634 /* Then try "double quotes". */
635 else if (p = strchr (oldq, '"'), p)
636 p++, q = strchr (p, '"');
637
638 /* Don't let the strstr's below see the demangled name; we
639 might get spurious matches. */
640 if (p)
641 p[-1] = '\0';
642
643 /* We need to check for certain error keywords here, or we would
644 mistakenly use GNU ld's "In function `foo':" message. */
645 if (q && (strstr (oldq, "ndefined")
646 || strstr (oldq, "nresolved")
647 || strstr (oldq, "nsatisfied")
648 || strstr (oldq, "ultiple")))
649 {
650 *q = 0;
651 dem = demangled_hash_lookup (p, false);
652 if (dem)
653 sym = symbol_hash_lookup (dem->mangled, false);
654 else
655 {
656 if (*p == '_' && prepends_underscore)
657 ++p;
658 sym = symbol_hash_lookup (p, false);
659 }
660 }
661 }
662
663 if (sym && sym->tweaked)
664 {
665 fclose (stream);
666 return 0;
667 }
668 if (sym && !sym->tweaking)
669 {
670 if (tlink_verbose >= 2)
671 fprintf (stderr, _("collect: tweaking %s in %s\n"),
672 sym->key, sym->file->key);
673 sym->tweaking = 1;
674 file_push (sym->file);
675 }
676
677 obstack_free (&temporary_obstack, temporary_firstobj);
678 }
679
680 fclose (stream);
681 return (file_stack != NULL);
682 }
683
684 /* Entry point for tlink. Called from main in collect2.c.
685
686 Iteratively try to provide definitions for all the unresolved symbols
687 mentioned in the linker error messages.
688
689 LD_ARGV is an array of arguments for the linker.
690 OBJECT_LST is an array of object files that we may be able to recompile
691 to provide missing definitions. Currently ignored. */
692
693 void
694 do_tlink (ld_argv, object_lst)
695 char **ld_argv, **object_lst ATTRIBUTE_UNUSED;
696 {
697 int exit = tlink_execute ("ld", ld_argv, ldout);
698
699 tlink_init ();
700
701 if (exit)
702 {
703 int i = 0;
704
705 /* Until collect does a better job of figuring out which are object
706 files, assume that everything on the command line could be. */
707 if (read_repo_files (ld_argv))
708 while (exit && i++ < MAX_ITERATIONS)
709 {
710 if (tlink_verbose >= 3)
711 dump_file (ldout);
712 demangle_new_symbols ();
713 if (! scan_linker_output (ldout))
714 break;
715 if (! recompile_files ())
716 break;
717 if (tlink_verbose)
718 fprintf (stderr, _("collect: relinking\n"));
719 exit = tlink_execute ("ld", ld_argv, ldout);
720 }
721 }
722
723 dump_file (ldout);
724 unlink (ldout);
725 if (exit)
726 {
727 error ("ld returned %d exit status", exit);
728 collect_exit (exit);
729 }
730 }