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