OSDN Git Service

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