OSDN Git Service

Fix another mips typo.
[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
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       if (!f->args)
474         {
475           error ("repository file `%s' does not contain command-line "
476                  "arguments", f->key);
477           return 0;
478         }
479       obstack_grow (&temporary_obstack, f->args, strlen (f->args));
480       obstack_1grow (&temporary_obstack, ' ');
481       command = obstack_copy0 (&temporary_obstack, f->main, strlen (f->main));
482
483       if (tlink_verbose)
484         fprintf (stderr, _("collect: recompiling %s\n"), f->main);
485       if (tlink_verbose >= 3)
486         fprintf (stderr, "%s\n", command);
487
488       if (system (command) != 0)
489         return 0;
490
491       read_repo_file (f);
492
493       obstack_free (&temporary_obstack, temporary_firstobj);
494     }
495   return 1;
496 }
497
498 /* The first phase of processing: determine which object files have
499    .rpo files associated with them, and read in the information.  */
500
501 static int
502 read_repo_files (char **object_lst)
503 {
504   char **object = object_lst;
505
506   for (; *object; object++)
507     {
508       const char *p;
509       file *f;
510
511       /* Don't bother trying for ld flags.  */
512       if (*object[0] == '-')
513         continue;
514
515       p = frob_extension (*object, ".rpo");
516
517       if (! file_exists (p))
518         continue;
519
520       f = file_hash_lookup (p);
521
522       read_repo_file (f);
523     }
524
525   if (file_stack != NULL && ! recompile_files ())
526     return 0;
527
528   return (symbol_stack != NULL);
529 }
530
531 /* Add the demangled forms of any new symbols to the hash table.  */
532
533 static void
534 demangle_new_symbols (void)
535 {
536   symbol *sym;
537
538   while ((sym = symbol_pop ()) != NULL)
539     {
540       demangled *dem;
541       const char *p = cplus_demangle (sym->key, DMGL_PARAMS | DMGL_ANSI);
542
543       if (! p)
544         continue;
545
546       dem = demangled_hash_lookup (p, true);
547       dem->mangled = sym->key;
548     }
549 }
550
551 /* Step through the output of the linker, in the file named FNAME, and
552    adjust the settings for each symbol encountered.  */
553
554 static int
555 scan_linker_output (const char *fname)
556 {
557   FILE *stream = fopen (fname, "r");
558   char *line;
559
560   while ((line = tfgets (stream)) != NULL)
561     {
562       char *p = line, *q;
563       symbol *sym;
564       int end;
565
566       while (*p && ISSPACE ((unsigned char) *p))
567         ++p;
568
569       if (! *p)
570         continue;
571
572       for (q = p; *q && ! ISSPACE ((unsigned char) *q); ++q)
573         ;
574
575       /* Try the first word on the line.  */
576       if (*p == '.')
577         ++p;
578       if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)))
579         p += strlen (USER_LABEL_PREFIX);
580
581       end = ! *q;
582       *q = 0;
583       sym = symbol_hash_lookup (p, false);
584
585       /* Some SVR4 linkers produce messages like
586          ld: 0711-317 ERROR: Undefined symbol: .g__t3foo1Zi
587          */
588       if (! sym && ! end && strstr (q + 1, "Undefined symbol: "))
589         {
590           char *p = strrchr (q + 1, ' ');
591           p++;
592           if (*p == '.')
593             p++;
594           if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)))
595             p += strlen (USER_LABEL_PREFIX);
596           sym = symbol_hash_lookup (p, false);
597         }
598
599       if (! sym && ! end)
600         /* Try a mangled name in quotes.  */
601         {
602           const char *oldq = q + 1;
603           demangled *dem = 0;
604           q = 0;
605
606           /* First try `GNU style'.  */
607           p = strchr (oldq, '`');
608           if (p)
609             p++, q = strchr (p, '\'');
610           /* Then try "double quotes".  */
611           else if (p = strchr (oldq, '"'), p)
612             p++, q = strchr (p, '"');
613           else {
614             /* Then try entire line.  */
615             q = strchr (oldq, 0);
616             if (q != oldq)
617               p = (char *)oldq;
618           }
619
620           if (p)
621             {
622               /* Don't let the strstr's below see the demangled name; we
623                  might get spurious matches.  */
624               p[-1] = '\0';
625
626               /* powerpc64-linux references .foo when calling function foo.  */
627               if (*p == '.')
628                 p++;
629             }
630
631           /* We need to check for certain error keywords here, or we would
632              mistakenly use GNU ld's "In function `foo':" message.  */
633           if (q && (strstr (oldq, "ndefined")
634                     || strstr (oldq, "nresolved")
635                     || strstr (oldq, "nsatisfied")
636                     || strstr (oldq, "ultiple")))
637             {
638               *q = 0;
639               dem = demangled_hash_lookup (p, false);
640               if (dem)
641                 sym = symbol_hash_lookup (dem->mangled, false);
642               else
643                 {
644                   if (!strncmp (p, USER_LABEL_PREFIX,
645                                 strlen (USER_LABEL_PREFIX)))
646                     p += strlen (USER_LABEL_PREFIX);
647                   sym = symbol_hash_lookup (p, false);
648                 }
649             }
650         }
651
652       if (sym && sym->tweaked)
653         {
654           error ("`%s' was assigned to `%s', but was not defined "
655                  "during recompilation, or vice versa", 
656                  sym->key, sym->file->key);
657           fclose (stream);
658           return 0;
659         }
660       if (sym && !sym->tweaking)
661         {
662           if (tlink_verbose >= 2)
663             fprintf (stderr, _("collect: tweaking %s in %s\n"),
664                      sym->key, sym->file->key);
665           sym->tweaking = 1;
666           file_push (sym->file);
667         }
668
669       obstack_free (&temporary_obstack, temporary_firstobj);
670     }
671
672   fclose (stream);
673   return (file_stack != NULL);
674 }
675
676 /* Entry point for tlink.  Called from main in collect2.c.
677
678    Iteratively try to provide definitions for all the unresolved symbols
679    mentioned in the linker error messages.
680
681    LD_ARGV is an array of arguments for the linker.
682    OBJECT_LST is an array of object files that we may be able to recompile
683      to provide missing definitions.  Currently ignored.  */
684
685 void
686 do_tlink (char **ld_argv, char **object_lst ATTRIBUTE_UNUSED)
687 {
688   int exit = tlink_execute ("ld", ld_argv, ldout);
689
690   tlink_init ();
691
692   if (exit)
693     {
694       int i = 0;
695
696       /* Until collect does a better job of figuring out which are object
697          files, assume that everything on the command line could be.  */
698       if (read_repo_files (ld_argv))
699         while (exit && i++ < MAX_ITERATIONS)
700           {
701             if (tlink_verbose >= 3)
702               dump_file (ldout);
703             demangle_new_symbols ();
704             if (! scan_linker_output (ldout))
705               break;
706             if (! recompile_files ())
707               break;
708             if (tlink_verbose)
709               fprintf (stderr, _("collect: relinking\n"));
710             exit = tlink_execute ("ld", ld_argv, ldout);
711           }
712     }
713
714   dump_file (ldout);
715   unlink (ldout);
716   if (exit)
717     {
718       error ("ld returned %d exit status", exit);
719       collect_exit (exit);
720     }
721 }