xref: /openbsd/gnu/usr.bin/gcc/gcc/tlink.c (revision 467ef1a3)
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 /* Defined in the automatically-generated underscore.c.  */
35 extern int prepends_underscore;
36 
37 static int tlink_verbose;
38 
39 /* Hash table boilerplate for working with htab_t.  We have hash tables
40    for symbol names, file names, and demangled symbols.  */
41 
42 typedef struct symbol_hash_entry
43 {
44   const char *key;
45   struct file_hash_entry *file;
46   int chosen;
47   int tweaking;
48   int tweaked;
49 } symbol;
50 
51 typedef struct file_hash_entry
52 {
53   const char *key;
54   const char *args;
55   const char *dir;
56   const char *main;
57   int tweaking;
58 } file;
59 
60 typedef struct demangled_hash_entry
61 {
62   const char *key;
63   const char *mangled;
64 } demangled;
65 
66 /* Hash and comparison functions for these hash tables.  */
67 
68 static int hash_string_eq PARAMS ((const void *, const void *));
69 static hashval_t hash_string_hash PARAMS ((const void *));
70 
71 static int
hash_string_eq(s1_p,s2_p)72 hash_string_eq (s1_p, s2_p)
73      const void *s1_p;
74      const void *s2_p;
75 {
76   const char *const *s1 = (const char *const *) s1_p;
77   const char *s2 = (const char *) s2_p;
78   return strcmp (*s1, s2) == 0;
79 }
80 
81 static hashval_t
hash_string_hash(s_p)82 hash_string_hash (s_p)
83      const void *s_p;
84 {
85   const char *const *s = (const char *const *) s_p;
86   return (*htab_hash_string) (*s);
87 }
88 
89 static htab_t symbol_table;
90 
91 static struct symbol_hash_entry * symbol_hash_lookup PARAMS ((const char *,
92 							      int));
93 static struct file_hash_entry * file_hash_lookup PARAMS ((const char *));
94 static struct demangled_hash_entry *
95   demangled_hash_lookup PARAMS ((const char *, int));
96 static void symbol_push PARAMS ((symbol *));
97 static symbol * symbol_pop PARAMS ((void));
98 static void file_push PARAMS ((file *));
99 static file * file_pop PARAMS ((void));
100 static void tlink_init PARAMS ((void));
101 static int tlink_execute PARAMS ((const char *, char **, const char *,
102 				  const char *));
103 static char * frob_extension PARAMS ((const char *, const char *));
104 static char * obstack_fgets PARAMS ((FILE *, struct obstack *));
105 static char * tfgets PARAMS ((FILE *));
106 static char * pfgets PARAMS ((FILE *));
107 static void freadsym PARAMS ((FILE *, file *, int));
108 static void read_repo_file PARAMS ((file *));
109 static void maybe_tweak PARAMS ((char *, file *));
110 static int recompile_files PARAMS ((void));
111 static int read_repo_files PARAMS ((char **));
112 static void demangle_new_symbols PARAMS ((void));
113 static int scan_linker_output PARAMS ((const char *));
114 
115 /* Look up an entry in the symbol hash table.  */
116 
117 static struct symbol_hash_entry *
symbol_hash_lookup(string,create)118 symbol_hash_lookup (string, create)
119      const char *string;
120      int create;
121 {
122   PTR *e;
123   e = htab_find_slot_with_hash (symbol_table, string,
124 				(*htab_hash_string) (string),
125 				create ? INSERT : NO_INSERT);
126   if (e == NULL)
127     return NULL;
128   if (*e == NULL)
129     {
130       struct symbol_hash_entry *v;
131       *e = v = xcalloc (1, sizeof (*v));
132       v->key = xstrdup (string);
133     }
134   return *e;
135 }
136 
137 static htab_t file_table;
138 
139 /* Look up an entry in the file hash table.  */
140 
141 static struct file_hash_entry *
file_hash_lookup(string)142 file_hash_lookup (string)
143      const char *string;
144 {
145   PTR *e;
146   e = htab_find_slot_with_hash (file_table, string,
147 				(*htab_hash_string) (string),
148 				INSERT);
149   if (*e == NULL)
150     {
151       struct file_hash_entry *v;
152       *e = v = xcalloc (1, sizeof (*v));
153       v->key = xstrdup (string);
154     }
155   return *e;
156 }
157 
158 static htab_t demangled_table;
159 
160 /* Look up an entry in the demangled name hash table.  */
161 
162 static struct demangled_hash_entry *
demangled_hash_lookup(string,create)163 demangled_hash_lookup (string, create)
164      const char *string;
165      int create;
166 {
167   PTR *e;
168   e = htab_find_slot_with_hash (demangled_table, string,
169 				(*htab_hash_string) (string),
170 				create ? INSERT : NO_INSERT);
171   if (e == NULL)
172     return NULL;
173   if (*e == NULL)
174     {
175       struct demangled_hash_entry *v;
176       *e = v = xcalloc (1, sizeof (*v));
177       v->key = xstrdup (string);
178     }
179   return *e;
180 }
181 
182 /* Stack code.  */
183 
184 struct symbol_stack_entry
185 {
186   symbol *value;
187   struct symbol_stack_entry *next;
188 };
189 struct obstack symbol_stack_obstack;
190 struct symbol_stack_entry *symbol_stack;
191 
192 struct file_stack_entry
193 {
194   file *value;
195   struct file_stack_entry *next;
196 };
197 struct obstack file_stack_obstack;
198 struct file_stack_entry *file_stack;
199 
200 static void
symbol_push(p)201 symbol_push (p)
202      symbol *p;
203 {
204   struct symbol_stack_entry *ep = (struct symbol_stack_entry *) obstack_alloc
205     (&symbol_stack_obstack, sizeof (struct symbol_stack_entry));
206   ep->value = p;
207   ep->next = symbol_stack;
208   symbol_stack = ep;
209 }
210 
211 static symbol *
symbol_pop()212 symbol_pop ()
213 {
214   struct symbol_stack_entry *ep = symbol_stack;
215   symbol *p;
216   if (ep == NULL)
217     return NULL;
218   p = ep->value;
219   symbol_stack = ep->next;
220   obstack_free (&symbol_stack_obstack, ep);
221   return p;
222 }
223 
224 static void
file_push(p)225 file_push (p)
226      file *p;
227 {
228   struct file_stack_entry *ep;
229 
230   if (p->tweaking)
231     return;
232 
233   ep = (struct file_stack_entry *) obstack_alloc
234     (&file_stack_obstack, sizeof (struct file_stack_entry));
235   ep->value = p;
236   ep->next = file_stack;
237   file_stack = ep;
238   p->tweaking = 1;
239 }
240 
241 static file *
file_pop()242 file_pop ()
243 {
244   struct file_stack_entry *ep = file_stack;
245   file *p;
246   if (ep == NULL)
247     return NULL;
248   p = ep->value;
249   file_stack = ep->next;
250   obstack_free (&file_stack_obstack, ep);
251   p->tweaking = 0;
252   return p;
253 }
254 
255 /* Other machinery.  */
256 
257 /* Initialize the tlink machinery.  Called from do_tlink.  */
258 
259 static void
tlink_init()260 tlink_init ()
261 {
262   const char *p;
263 
264   symbol_table = htab_create (500, hash_string_hash, hash_string_eq,
265 			      NULL);
266   file_table = htab_create (500, hash_string_hash, hash_string_eq,
267 			    NULL);
268   demangled_table = htab_create (500, hash_string_hash, hash_string_eq,
269 				 NULL);
270 
271   obstack_begin (&symbol_stack_obstack, 0);
272   obstack_begin (&file_stack_obstack, 0);
273 
274   p = getenv ("TLINK_VERBOSE");
275   if (p)
276     tlink_verbose = atoi (p);
277   else
278     {
279       tlink_verbose = 1;
280       if (vflag)
281 	tlink_verbose = 2;
282       if (debug)
283 	tlink_verbose = 3;
284     }
285 }
286 
287 static int
tlink_execute(prog,argv,outname,errname)288 tlink_execute (prog, argv, outname, errname)
289      const char *prog;
290      char **argv;
291      const char *outname;
292      const char *errname;
293 {
294   collect_execute (prog, argv, outname, errname);
295   return collect_wait (prog);
296 }
297 
298 static char *
frob_extension(s,ext)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 *
obstack_fgets(stream,ob)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 *
tfgets(stream)329 tfgets (stream)
330      FILE *stream;
331 {
332   return obstack_fgets (stream, &temporary_obstack);
333 }
334 
335 static char *
pfgets(stream)336 pfgets (stream)
337      FILE *stream;
338 {
339   return xstrdup (tfgets (stream));
340 }
341 
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 offerred, 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
freadsym(stream,f,chosen)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
read_repo_file(f)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
maybe_tweak(line,f)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
recompile_files()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
read_repo_files(object_lst)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
demangle_new_symbols()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
scan_linker_output(fname)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 	  if (p)
637 	    {
638 	      /* Don't let the strstr's below see the demangled name; we
639 		 might get spurious matches.  */
640 	      p[-1] = '\0';
641 
642 	      /* powerpc64-linux references .foo when calling function foo.  */
643 	      if (*p == '.')
644 		p++;
645 	    }
646 
647 	  /* We need to check for certain error keywords here, or we would
648 	     mistakenly use GNU ld's "In function `foo':" message.  */
649 	  if (q && (strstr (oldq, "ndefined")
650 		    || strstr (oldq, "nresolved")
651 		    || strstr (oldq, "nsatisfied")
652 		    || strstr (oldq, "ultiple")))
653 	    {
654 	      *q = 0;
655 	      dem = demangled_hash_lookup (p, false);
656 	      if (dem)
657 		sym = symbol_hash_lookup (dem->mangled, false);
658 	      else
659 		{
660 		  if (!strncmp (p, USER_LABEL_PREFIX,
661 				strlen (USER_LABEL_PREFIX)))
662 		    p += strlen (USER_LABEL_PREFIX);
663 		  sym = symbol_hash_lookup (p, false);
664 		}
665 	    }
666 	}
667 
668       if (sym && sym->tweaked)
669 	{
670 	  fclose (stream);
671 	  return 0;
672 	}
673       if (sym && !sym->tweaking)
674 	{
675 	  if (tlink_verbose >= 2)
676 	    fprintf (stderr, _("collect: tweaking %s in %s\n"),
677 		     sym->key, sym->file->key);
678 	  sym->tweaking = 1;
679 	  file_push (sym->file);
680 	}
681 
682       obstack_free (&temporary_obstack, temporary_firstobj);
683     }
684 
685   fclose (stream);
686   return (file_stack != NULL);
687 }
688 
689 /* Entry point for tlink.  Called from main in collect2.c.
690 
691    Iteratively try to provide definitions for all the unresolved symbols
692    mentioned in the linker error messages.
693 
694    LD_ARGV is an array of arguments for the linker.
695    OBJECT_LST is an array of object files that we may be able to recompile
696      to provide missing definitions.  Currently ignored.  */
697 
698 void
do_tlink(ld_argv,object_lst)699 do_tlink (ld_argv, object_lst)
700      char **ld_argv, **object_lst ATTRIBUTE_UNUSED;
701 {
702   int exit = tlink_execute ("ld", ld_argv, ldout, lderrout);
703 
704   tlink_init ();
705 
706   if (exit)
707     {
708       int i = 0;
709 
710       /* Until collect does a better job of figuring out which are object
711 	 files, assume that everything on the command line could be.  */
712       if (read_repo_files (ld_argv))
713 	while (exit && i++ < MAX_ITERATIONS)
714 	  {
715 	    if (tlink_verbose >= 3)
716 	      {
717 	        dump_file (ldout, stdout);
718 	        dump_file (lderrout, stderr);
719 	      }
720 	    demangle_new_symbols ();
721 	    if (! scan_linker_output (ldout)
722 	        && ! scan_linker_output (lderrout))
723 	      break;
724 	    if (! recompile_files ())
725 	      break;
726 	    if (tlink_verbose)
727 	      fprintf (stderr, _("collect: relinking\n"));
728 	    exit = tlink_execute ("ld", ld_argv, ldout, lderrout);
729 	  }
730     }
731 
732   dump_file (ldout, stdout);
733   dump_file (lderrout, stderr);
734   unlink (ldout);
735   unlink (lderrout);
736   if (exit)
737     {
738       error ("ld returned %d exit status", exit);
739       collect_exit (exit);
740     }
741 }
742