OSDN Git Service

bf4e1d757b0f3dcfc9f9f30413a0a300a61e7e21
[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, 1999, 2000, 2001, 2003, 2004, 2005
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   struct pex_obj *pex;
285
286   pex = collect_execute (prog, argv, redir);
287   return collect_wait (prog, pex);
288 }
289
290 static char *
291 frob_extension (const char *s, const char *ext)
292 {
293   const char *p = strrchr (s, '/');
294   if (! p)
295     p = s;
296   p = strrchr (p, '.');
297   if (! p)
298     p = s + strlen (s);
299
300   obstack_grow (&temporary_obstack, s, p - s);
301   return obstack_copy0 (&temporary_obstack, ext, strlen (ext));
302 }
303
304 static char *
305 obstack_fgets (FILE *stream, struct obstack *ob)
306 {
307   int c;
308   while ((c = getc (stream)) != EOF && c != '\n')
309     obstack_1grow (ob, c);
310   if (obstack_object_size (ob) == 0)
311     return NULL;
312   obstack_1grow (ob, '\0');
313   return obstack_finish (ob);
314 }
315
316 static char *
317 tfgets (FILE *stream)
318 {
319   return obstack_fgets (stream, &temporary_obstack);
320 }
321
322 static char *
323 pfgets (FILE *stream)
324 {
325   return xstrdup (tfgets (stream));
326 }
327 \f
328 /* Real tlink code.  */
329
330 /* Subroutine of read_repo_file.  We are reading the repo file for file F,
331    which is coming in on STREAM, and the symbol that comes next in STREAM
332    is offered, chosen or provided if CHOSEN is 0, 1 or 2, respectively.
333
334    XXX "provided" is unimplemented, both here and in the compiler.  */
335
336 static void
337 freadsym (FILE *stream, file *f, int chosen)
338 {
339   symbol *sym;
340
341   {
342     const char *name = tfgets (stream);
343     sym = symbol_hash_lookup (name, true);
344   }
345
346   if (sym->file == NULL)
347     {
348       /* We didn't have this symbol already, so we choose this file.  */
349
350       symbol_push (sym);
351       sym->file = f;
352       sym->chosen = chosen;
353     }
354   else if (chosen)
355     {
356       /* We want this file; cast aside any pretender.  */
357
358       if (sym->chosen && sym->file != f)
359         {
360           if (sym->chosen == 1)
361             file_push (sym->file);
362           else
363             {
364               file_push (f);
365               f = sym->file;
366               chosen = sym->chosen;
367             }
368         }
369       sym->file = f;
370       sym->chosen = chosen;
371     }
372 }
373
374 /* Read in the repo file denoted by F, and record all its information.  */
375
376 static void
377 read_repo_file (file *f)
378 {
379   char c;
380   FILE *stream = fopen (f->key, "r");
381
382   if (tlink_verbose >= 2)
383     fprintf (stderr, _("collect: reading %s\n"), f->key);
384
385   while (fscanf (stream, "%c ", &c) == 1)
386     {
387       switch (c)
388         {
389         case 'A':
390           f->args = pfgets (stream);
391           break;
392         case 'D':
393           f->dir = pfgets (stream);
394           break;
395         case 'M':
396           f->main = pfgets (stream);
397           break;
398         case 'P':
399           freadsym (stream, f, 2);
400           break;
401         case 'C':
402           freadsym (stream, f, 1);
403           break;
404         case 'O':
405           freadsym (stream, f, 0);
406           break;
407         }
408       obstack_free (&temporary_obstack, temporary_firstobj);
409     }
410   fclose (stream);
411   if (f->args == NULL)
412     f->args = getenv ("COLLECT_GCC_OPTIONS");
413   if (f->dir == NULL)
414     f->dir = ".";
415 }
416
417 /* We might want to modify LINE, which is a symbol line from file F.  We do
418    this if either we saw an error message referring to the symbol in
419    question, or we have already allocated the symbol to another file and
420    this one wants to emit it as well.  */
421
422 static void
423 maybe_tweak (char *line, file *f)
424 {
425   symbol *sym = symbol_hash_lookup (line + 2, false);
426
427   if ((sym->file == f && sym->tweaking)
428       || (sym->file != f && line[0] == 'C'))
429     {
430       sym->tweaking = 0;
431       sym->tweaked = 1;
432
433       if (line[0] == 'O')
434         line[0] = 'C';
435       else
436         line[0] = 'O';
437     }
438 }
439
440 /* Update the repo files for each of the object files we have adjusted and
441    recompile.  */
442
443 static int
444 recompile_files (void)
445 {
446   file *f;
447
448   putenv (xstrdup ("COMPILER_PATH="));
449   putenv (xstrdup ("LIBRARY_PATH="));
450
451   while ((f = file_pop ()) != NULL)
452     {
453       char *line;
454       const char *p, *q;
455       char **argv;
456       struct obstack arg_stack;
457       FILE *stream = fopen (f->key, "r");
458       const char *const outname = frob_extension (f->key, ".rnw");
459       FILE *output = fopen (outname, "w");
460
461       while ((line = tfgets (stream)) != NULL)
462         {
463           switch (line[0])
464             {
465             case 'C':
466             case 'O':
467               maybe_tweak (line, f);
468             }
469           fprintf (output, "%s\n", line);
470         }
471       fclose (stream);
472       fclose (output);
473       rename (outname, f->key);
474
475       if (!f->args)
476         {
477           error ("repository file '%s' does not contain command-line "
478                  "arguments", f->key);
479           return 0;
480         }
481
482       /* Build a null-terminated argv array suitable for
483          tlink_execute().  Manipulate arguments on the arg_stack while
484          building argv on the temporary_obstack.  */
485
486       obstack_init (&arg_stack);
487       obstack_ptr_grow (&temporary_obstack, c_file_name);
488
489       for (p = f->args; *p != '\0'; p = q + 1)
490         {
491           /* Arguments are delimited by single-quotes.  Find the
492              opening quote.  */
493           p = strchr (p, '\'');
494           if (!p)
495             goto done;
496
497           /* Find the closing quote.  */
498           q = strchr (p + 1, '\'');
499           if (!q)
500             goto done;
501
502           obstack_grow (&arg_stack, p + 1, q - (p + 1));
503
504           /* Replace '\'' with '.  This is how set_collect_gcc_options
505              encodes a single-quote.  */
506           while (q[1] == '\\' && q[2] == '\'' && q[3] == '\'')
507             {
508               const char *r;
509
510               r = strchr (q + 4, '\'');
511               if (!r)
512                 goto done;
513
514               obstack_grow (&arg_stack, q + 3, r - (q + 3));
515               q = r;
516             }
517
518           obstack_1grow (&arg_stack, '\0');
519           obstack_ptr_grow (&temporary_obstack, obstack_finish (&arg_stack));
520         }
521     done:
522       obstack_ptr_grow (&temporary_obstack, f->main);
523       obstack_ptr_grow (&temporary_obstack, NULL);
524       argv = obstack_finish (&temporary_obstack);
525
526       if (tlink_verbose)
527         fprintf (stderr, _("collect: recompiling %s\n"), f->main);
528
529       if (chdir (f->dir) != 0
530           || tlink_execute (c_file_name, argv, NULL) != 0
531           || chdir (initial_cwd) != 0)
532         return 0;
533
534       read_repo_file (f);
535
536       obstack_free (&arg_stack, NULL);
537       obstack_free (&temporary_obstack, temporary_firstobj);
538     }
539   return 1;
540 }
541
542 /* The first phase of processing: determine which object files have
543    .rpo files associated with them, and read in the information.  */
544
545 static int
546 read_repo_files (char **object_lst)
547 {
548   char **object = object_lst;
549
550   for (; *object; object++)
551     {
552       const char *p;
553       file *f;
554
555       /* Don't bother trying for ld flags.  */
556       if (*object[0] == '-')
557         continue;
558
559       p = frob_extension (*object, ".rpo");
560
561       if (! file_exists (p))
562         continue;
563
564       f = file_hash_lookup (p);
565
566       read_repo_file (f);
567     }
568
569   if (file_stack != NULL && ! recompile_files ())
570     return 0;
571
572   return (symbol_stack != NULL);
573 }
574
575 /* Add the demangled forms of any new symbols to the hash table.  */
576
577 static void
578 demangle_new_symbols (void)
579 {
580   symbol *sym;
581
582   while ((sym = symbol_pop ()) != NULL)
583     {
584       demangled *dem;
585       const char *p = cplus_demangle (sym->key, DMGL_PARAMS | DMGL_ANSI);
586
587       if (! p)
588         continue;
589
590       dem = demangled_hash_lookup (p, true);
591       dem->mangled = sym->key;
592     }
593 }
594
595 /* Step through the output of the linker, in the file named FNAME, and
596    adjust the settings for each symbol encountered.  */
597
598 static int
599 scan_linker_output (const char *fname)
600 {
601   FILE *stream = fopen (fname, "r");
602   char *line;
603
604   while ((line = tfgets (stream)) != NULL)
605     {
606       char *p = line, *q;
607       symbol *sym;
608       int end;
609
610       while (*p && ISSPACE ((unsigned char) *p))
611         ++p;
612
613       if (! *p)
614         continue;
615
616       for (q = p; *q && ! ISSPACE ((unsigned char) *q); ++q)
617         ;
618
619       /* Try the first word on the line.  */
620       if (*p == '.')
621         ++p;
622       if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)))
623         p += strlen (USER_LABEL_PREFIX);
624
625       end = ! *q;
626       *q = 0;
627       sym = symbol_hash_lookup (p, false);
628
629       /* Some SVR4 linkers produce messages like
630          ld: 0711-317 ERROR: Undefined symbol: .g__t3foo1Zi
631          */
632       if (! sym && ! end && strstr (q + 1, "Undefined symbol: "))
633         {
634           char *p = strrchr (q + 1, ' ');
635           p++;
636           if (*p == '.')
637             p++;
638           if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)))
639             p += strlen (USER_LABEL_PREFIX);
640           sym = symbol_hash_lookup (p, false);
641         }
642
643       if (! sym && ! end)
644         /* Try a mangled name in quotes.  */
645         {
646           const char *oldq = q + 1;
647           demangled *dem = 0;
648           q = 0;
649
650           /* First try `GNU style'.  */
651           p = strchr (oldq, '`');
652           if (p)
653             p++, q = strchr (p, '\'');
654           /* Then try "double quotes".  */
655           else if (p = strchr (oldq, '"'), p)
656             p++, q = strchr (p, '"');
657           else {
658             /* Then try entire line.  */
659             q = strchr (oldq, 0);
660             if (q != oldq)
661               p = (char *)oldq;
662           }
663
664           if (p)
665             {
666               /* Don't let the strstr's below see the demangled name; we
667                  might get spurious matches.  */
668               p[-1] = '\0';
669
670               /* powerpc64-linux references .foo when calling function foo.  */
671               if (*p == '.')
672                 p++;
673             }
674
675           /* We need to check for certain error keywords here, or we would
676              mistakenly use GNU ld's "In function `foo':" message.  */
677           if (q && (strstr (oldq, "ndefined")
678                     || strstr (oldq, "nresolved")
679                     || strstr (oldq, "nsatisfied")
680                     || strstr (oldq, "ultiple")))
681             {
682               *q = 0;
683               dem = demangled_hash_lookup (p, false);
684               if (dem)
685                 sym = symbol_hash_lookup (dem->mangled, false);
686               else
687                 {
688                   if (!strncmp (p, USER_LABEL_PREFIX,
689                                 strlen (USER_LABEL_PREFIX)))
690                     p += strlen (USER_LABEL_PREFIX);
691                   sym = symbol_hash_lookup (p, false);
692                 }
693             }
694         }
695
696       if (sym && sym->tweaked)
697         {
698           error ("'%s' was assigned to '%s', but was not defined "
699                  "during recompilation, or vice versa", 
700                  sym->key, sym->file->key);
701           fclose (stream);
702           return 0;
703         }
704       if (sym && !sym->tweaking)
705         {
706           if (tlink_verbose >= 2)
707             fprintf (stderr, _("collect: tweaking %s in %s\n"),
708                      sym->key, sym->file->key);
709           sym->tweaking = 1;
710           file_push (sym->file);
711         }
712
713       obstack_free (&temporary_obstack, temporary_firstobj);
714     }
715
716   fclose (stream);
717   return (file_stack != NULL);
718 }
719
720 /* Entry point for tlink.  Called from main in collect2.c.
721
722    Iteratively try to provide definitions for all the unresolved symbols
723    mentioned in the linker error messages.
724
725    LD_ARGV is an array of arguments for the linker.
726    OBJECT_LST is an array of object files that we may be able to recompile
727      to provide missing definitions.  Currently ignored.  */
728
729 void
730 do_tlink (char **ld_argv, char **object_lst ATTRIBUTE_UNUSED)
731 {
732   int exit = tlink_execute ("ld", ld_argv, ldout);
733
734   tlink_init ();
735
736   if (exit)
737     {
738       int i = 0;
739
740       /* Until collect does a better job of figuring out which are object
741          files, assume that everything on the command line could be.  */
742       if (read_repo_files (ld_argv))
743         while (exit && i++ < MAX_ITERATIONS)
744           {
745             if (tlink_verbose >= 3)
746               dump_file (ldout);
747             demangle_new_symbols ();
748             if (! scan_linker_output (ldout))
749               break;
750             if (! recompile_files ())
751               break;
752             if (tlink_verbose)
753               fprintf (stderr, _("collect: relinking\n"));
754             exit = tlink_execute ("ld", ld_argv, ldout);
755           }
756     }
757
758   dump_file (ldout);
759   unlink (ldout);
760   if (exit)
761     {
762       error ("ld returned %d exit status", exit);
763       collect_exit (exit);
764     }
765 }