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