OSDN Git Service

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