]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/tlink.c
c-lang.c (finish_file): Bracket declaration of static_ctors, static_dtors.
[thirdparty/gcc.git] / gcc / tlink.c
1 /* Scan linker error messages for missing template instantiations and provide
2 them.
3
4 Copyright (C) 1995 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
22
23 #include <stdio.h>
24 #include <ctype.h>
25 #include "config.h"
26 #include "hash.h"
27 #include "demangle.h"
28
29 #ifdef HAVE_STDLIB_H
30 #include <stdlib.h>
31 #endif
32
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36
37 #ifdef HAVE_STRING_H
38 #include <string.h>
39 #else
40 #ifdef HAVE_STRINGS_H
41 #include <strings.h>
42 #endif
43 #endif
44
45 #define MAX_ITERATIONS 17
46
47 /* Obstack allocation and deallocation routines. */
48 #define obstack_chunk_alloc xmalloc
49 #define obstack_chunk_free free
50
51 extern char * xmalloc PARAMS((unsigned));
52 extern void free ();
53 extern char * getenv ();
54
55 /* Defined in collect2.c. */
56 extern int vflag, debug;
57 extern char *ldout;
58 extern char *c_file_name;
59 extern struct obstack temporary_obstack;
60 extern struct obstack permanent_obstack;
61 extern char * temporary_firstobj;
62
63 /* Defined in the automatically-generated underscore.c. */
64 extern int prepends_underscore;
65
66 static int tlink_verbose;
67 \f
68 /* Hash table code. */
69
70 typedef struct symbol_hash_entry
71 {
72 struct hash_entry root;
73 struct file_hash_entry *file;
74 int chosen;
75 int tweaking;
76 int tweaked;
77 } symbol;
78
79 typedef struct file_hash_entry
80 {
81 struct hash_entry root;
82 const char *args;
83 const char *dir;
84 const char *main;
85 int tweaking;
86 } file;
87
88 typedef struct demangled_hash_entry
89 {
90 struct hash_entry root;
91 const char *mangled;
92 } demangled;
93
94 static struct hash_table symbol_table;
95
96 static struct hash_entry *
97 symbol_hash_newfunc (entry, table, string)
98 struct hash_entry *entry;
99 struct hash_table *table;
100 const char *string;
101 {
102 struct symbol_hash_entry *ret = (struct symbol_hash_entry *) entry;
103 if (ret == NULL)
104 {
105 ret = ((struct symbol_hash_entry *)
106 hash_allocate (table, sizeof (struct symbol_hash_entry)));
107 if (ret == NULL)
108 return NULL;
109 }
110 ret = ((struct symbol_hash_entry *)
111 hash_newfunc ((struct hash_entry *) ret, table, string));
112 ret->file = NULL;
113 ret->chosen = 0;
114 ret->tweaking = 0;
115 ret->tweaked = 0;
116 return (struct hash_entry *) ret;
117 }
118
119 static struct symbol_hash_entry *
120 symbol_hash_lookup (string, create)
121 const char *string;
122 boolean create;
123 {
124 return ((struct symbol_hash_entry *)
125 hash_lookup (&symbol_table, string, create, true));
126 }
127
128 static struct hash_table file_table;
129
130 static struct hash_entry *
131 file_hash_newfunc (entry, table, string)
132 struct hash_entry *entry;
133 struct hash_table *table;
134 const char *string;
135 {
136 struct file_hash_entry *ret = (struct file_hash_entry *) entry;
137 if (ret == NULL)
138 {
139 ret = ((struct file_hash_entry *)
140 hash_allocate (table, sizeof (struct file_hash_entry)));
141 if (ret == NULL)
142 return NULL;
143 }
144 ret = ((struct file_hash_entry *)
145 hash_newfunc ((struct hash_entry *) ret, table, string));
146 ret->args = NULL;
147 ret->dir = NULL;
148 ret->main = NULL;
149 ret->tweaking = 0;
150 return (struct hash_entry *) ret;
151 }
152
153 static struct file_hash_entry *
154 file_hash_lookup (string)
155 const char *string;
156 {
157 return ((struct file_hash_entry *)
158 hash_lookup (&file_table, string, true, true));
159 }
160
161 static struct hash_table demangled_table;
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, string));
179 ret->mangled = NULL;
180 return (struct hash_entry *) ret;
181 }
182
183 static struct demangled_hash_entry *
184 demangled_hash_lookup (string, create)
185 const char *string;
186 boolean create;
187 {
188 return ((struct demangled_hash_entry *)
189 hash_lookup (&demangled_table, string, create, true));
190 }
191 \f
192 /* Stack code. */
193
194 struct symbol_stack_entry
195 {
196 symbol *value;
197 struct symbol_stack_entry *next;
198 };
199 struct obstack symbol_stack_obstack;
200 struct symbol_stack_entry *symbol_stack;
201
202 struct file_stack_entry
203 {
204 file *value;
205 struct file_stack_entry *next;
206 };
207 struct obstack file_stack_obstack;
208 struct file_stack_entry *file_stack;
209
210 static void
211 symbol_push (p)
212 symbol *p;
213 {
214 struct symbol_stack_entry *ep = (struct symbol_stack_entry *) obstack_alloc
215 (&symbol_stack_obstack, sizeof (struct symbol_stack_entry));
216 ep->value = p;
217 ep->next = symbol_stack;
218 symbol_stack = ep;
219 }
220
221 static symbol *
222 symbol_pop ()
223 {
224 struct symbol_stack_entry *ep = symbol_stack;
225 symbol *p;
226 if (ep == NULL)
227 return NULL;
228 p = ep->value;
229 symbol_stack = ep->next;
230 obstack_free (&symbol_stack_obstack, ep);
231 return p;
232 }
233
234 static void
235 file_push (p)
236 file *p;
237 {
238 struct file_stack_entry *ep;
239
240 if (p->tweaking)
241 return;
242
243 ep = (struct file_stack_entry *) obstack_alloc
244 (&file_stack_obstack, sizeof (struct file_stack_entry));
245 ep->value = p;
246 ep->next = file_stack;
247 file_stack = ep;
248 p->tweaking = 1;
249 }
250
251 static file *
252 file_pop ()
253 {
254 struct file_stack_entry *ep = file_stack;
255 file *p;
256 if (ep == NULL)
257 return NULL;
258 p = ep->value;
259 file_stack = ep->next;
260 obstack_free (&file_stack_obstack, ep);
261 p->tweaking = 0;
262 return p;
263 }
264 \f
265 /* Other machinery. */
266
267 static void
268 tlink_init ()
269 {
270 char *p;
271
272 hash_table_init (&symbol_table, symbol_hash_newfunc);
273 hash_table_init (&file_table, file_hash_newfunc);
274 hash_table_init (&demangled_table, demangled_hash_newfunc);
275 obstack_begin (&symbol_stack_obstack, 0);
276 obstack_begin (&file_stack_obstack, 0);
277
278 p = getenv ("TLINK_VERBOSE");
279 if (p)
280 tlink_verbose = atoi (p);
281 else
282 {
283 tlink_verbose = 1;
284 if (vflag)
285 tlink_verbose = 2;
286 if (debug)
287 tlink_verbose = 3;
288 }
289 }
290
291 static int
292 tlink_execute (prog, argv, redir)
293 char *prog;
294 char **argv;
295 char *redir;
296 {
297 collect_execute (prog, argv, redir);
298 return collect_wait (prog);
299 }
300
301 static char *
302 frob_extension (s, ext)
303 char *s, *ext;
304 {
305 char *p = (char *) rindex (s, '/');
306 if (! p)
307 p = s;
308 p = (char *) rindex (p, '.');
309 if (! p)
310 p = s + strlen (s);
311
312 obstack_grow (&temporary_obstack, s, p - s);
313 return obstack_copy0 (&temporary_obstack, ext, strlen (ext));
314 }
315
316 static char *
317 obstack_fgets (stream, ob)
318 FILE *stream;
319 struct obstack *ob;
320 {
321 int c;
322 while ((c = getc (stream)) != EOF && c != '\n')
323 obstack_1grow (ob, c);
324 if (obstack_object_size (ob) == 0)
325 return NULL;
326 obstack_1grow (ob, '\0');
327 return obstack_finish (ob);
328 }
329
330 static char *
331 tfgets (stream)
332 FILE *stream;
333 {
334 return obstack_fgets (stream, &temporary_obstack);
335 }
336
337 static char *
338 pfgets (stream)
339 FILE *stream;
340 {
341 return obstack_fgets (stream, &permanent_obstack);
342 }
343 \f
344 /* Real tlink code. */
345
346 static void
347 freadsym (stream, f, chosen)
348 FILE *stream;
349 file *f;
350 int chosen;
351 {
352 symbol *sym;
353
354 {
355 char *name = tfgets (stream);
356 sym = symbol_hash_lookup (name, true);
357 }
358
359 if (sym->file == NULL)
360 {
361 symbol_push (sym);
362 sym->file = f;
363 sym->chosen = chosen;
364 }
365 else if (chosen)
366 {
367 if (sym->chosen && sym->file != f)
368 {
369 if (sym->chosen == 1)
370 file_push (sym->file);
371 else
372 {
373 file_push (f);
374 f = sym->file;
375 chosen = sym->chosen;
376 }
377 }
378 sym->file = f;
379 sym->chosen = chosen;
380 }
381 }
382
383 static void
384 read_repo_file (f)
385 file *f;
386 {
387 char c;
388 FILE *stream = fopen (f->root.string, "r");
389
390 if (tlink_verbose >= 2)
391 fprintf (stderr, "collect: reading %s\n", f->root.string);
392
393 while (fscanf (stream, "%c ", &c) == 1)
394 {
395 switch (c)
396 {
397 case 'A':
398 f->args = pfgets (stream);
399 break;
400 case 'D':
401 f->dir = pfgets (stream);
402 break;
403 case 'M':
404 f->main = pfgets (stream);
405 break;
406 case 'P':
407 freadsym (stream, f, 2);
408 break;
409 case 'C':
410 freadsym (stream, f, 1);
411 break;
412 case 'O':
413 freadsym (stream, f, 0);
414 break;
415 }
416 obstack_free (&temporary_obstack, temporary_firstobj);
417 }
418 fclose (stream);
419 if (f->args == NULL)
420 f->args = getenv ("COLLECT_GCC_OPTIONS");
421 if (f->dir == NULL)
422 f->dir = ".";
423 }
424
425 static void
426 maybe_tweak (line, f)
427 char *line;
428 file *f;
429 {
430 symbol *sym = symbol_hash_lookup (line + 2, false);
431
432 if ((sym->file == f && sym->tweaking)
433 || (sym->file != f && line[0] == 'C'))
434 {
435 sym->tweaking = 0;
436 sym->tweaked = 1;
437
438 if (line[0] == 'O')
439 line[0] = 'C';
440 else
441 line[0] = 'O';
442 }
443 }
444
445 static int
446 recompile_files ()
447 {
448 file *f;
449
450 while ((f = file_pop ()) != NULL)
451 {
452 char *line, *command;
453 FILE *stream = fopen (f->root.string, "r");
454 char *outname = frob_extension (f->root.string, ".rnw");
455 FILE *output = fopen (outname, "w");
456
457 while ((line = tfgets (stream)) != NULL)
458 {
459 switch (line[0])
460 {
461 case 'C':
462 case 'O':
463 maybe_tweak (line, f);
464 }
465 fprintf (output, "%s\n", line);
466 }
467 fclose (stream);
468 fclose (output);
469 rename (outname, f->root.string);
470
471 obstack_grow (&temporary_obstack, "cd ", 3);
472 obstack_grow (&temporary_obstack, f->dir, strlen (f->dir));
473 obstack_grow (&temporary_obstack, "; ", 2);
474 obstack_grow (&temporary_obstack, c_file_name, strlen (c_file_name));
475 obstack_1grow (&temporary_obstack, ' ');
476 obstack_grow (&temporary_obstack, f->args, strlen (f->args));
477 obstack_1grow (&temporary_obstack, ' ');
478 command = obstack_copy0 (&temporary_obstack, f->main, strlen (f->main));
479
480 if (tlink_verbose)
481 fprintf (stderr, "collect: recompiling %s\n", f->main);
482 if (tlink_verbose >= 3)
483 fprintf (stderr, "%s\n", command);
484
485 if (system (command) != 0)
486 return 0;
487
488 read_repo_file (f);
489
490 obstack_free (&temporary_obstack, temporary_firstobj);
491 }
492 return 1;
493 }
494
495 static int
496 read_repo_files (object_lst)
497 char **object_lst;
498 {
499 char **object = object_lst;
500
501 for (; *object; object++)
502 {
503 char *p = frob_extension (*object, ".rpo");
504 file *f;
505
506 if (! file_exists (p))
507 continue;
508
509 f = file_hash_lookup (p);
510
511 read_repo_file (f);
512 }
513
514 if (file_stack != NULL && ! recompile_files ())
515 return 0;
516
517 return (symbol_stack != NULL);
518 }
519
520 static void
521 demangle_new_symbols ()
522 {
523 symbol *sym;
524
525 while ((sym = symbol_pop ()) != NULL)
526 {
527 demangled *dem;
528 char *p = cplus_demangle (sym->root.string, DMGL_PARAMS | DMGL_ANSI);
529
530 if (! p)
531 continue;
532
533 dem = demangled_hash_lookup (p, true);
534 dem->mangled = sym->root.string;
535 }
536 }
537
538 static int
539 scan_linker_output (fname)
540 char *fname;
541 {
542 FILE *stream = fopen (fname, "r");
543 char *line;
544
545 while ((line = tfgets (stream)) != NULL)
546 {
547 char *p = line, *q;
548 symbol *sym;
549 int end;
550
551 while (*p && isspace (*p))
552 ++p;
553
554 if (! *p)
555 continue;
556
557 for (q = p; *q && ! isspace (*q); ++q)
558 ;
559
560 /* Try the first word on the line. */
561 if (*p == '.')
562 ++p;
563 if (*p == '_' && prepends_underscore)
564 ++p;
565
566 end = ! *q;
567 *q = 0;
568 sym = symbol_hash_lookup (p, false);
569
570 if (! sym && ! end)
571 /* Try a mangled name in `quotes'. */
572 {
573 demangled *dem = 0;
574 p = (char *) index (q+1, '`');
575 q = 0;
576
577 #define MUL "multiple definition of "
578 #define UND "undefined reference to "
579
580 if (p && (p - line > sizeof (MUL)))
581 {
582 char *beg = p - sizeof (MUL) + 1;
583 *p = 0;
584 if (!strcmp (beg, MUL) || !strcmp (beg, UND))
585 p++, q = (char *) index (p, '\'');
586 }
587 if (q)
588 *q = 0, dem = demangled_hash_lookup (p, false);
589 if (dem)
590 sym = symbol_hash_lookup (dem->mangled, false);
591 }
592
593 if (sym && sym->tweaked)
594 {
595 fclose (stream);
596 return 0;
597 }
598 if (sym && !sym->tweaking)
599 {
600 if (tlink_verbose >= 2)
601 fprintf (stderr, "collect: tweaking %s in %s\n",
602 sym->root.string, sym->file->root.string);
603 sym->tweaking = 1;
604 file_push (sym->file);
605 }
606
607 obstack_free (&temporary_obstack, temporary_firstobj);
608 }
609
610 fclose (stream);
611 return (file_stack != NULL);
612 }
613
614 void
615 do_tlink (ld_argv, object_lst)
616 char **ld_argv, **object_lst;
617 {
618 int exit = tlink_execute ("ld", ld_argv, ldout);
619
620 tlink_init ();
621
622 if (exit)
623 {
624 int i = 0;
625
626 /* Until collect does a better job of figuring out which are object
627 files, assume that everything on the command line could be. */
628 if (read_repo_files (ld_argv))
629 while (exit && i++ < MAX_ITERATIONS)
630 {
631 if (tlink_verbose >= 3)
632 dump_file (ldout);
633 demangle_new_symbols ();
634 if (! scan_linker_output (ldout))
635 break;
636 if (! recompile_files ())
637 break;
638 if (tlink_verbose)
639 fprintf (stderr, "collect: relinking\n");
640 exit = tlink_execute ("ld", ld_argv, ldout);
641 }
642 }
643
644 dump_file (ldout);
645 unlink (ldout);
646 if (exit)
647 {
648 error ("ld returned %d exit status", exit);
649 collect_exit (exit);
650 }
651 }