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