xref: /dflybsd-src/contrib/gcc-4.7/gcc/tlink.c (revision 0a8dc9fc45f4d0b236341a473fac4a486375f60c)
1e4b17023SJohn Marino /* Scan linker error messages for missing template instantiations and provide
2e4b17023SJohn Marino    them.
3e4b17023SJohn Marino 
4e4b17023SJohn Marino    Copyright (C) 1995, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2007, 2008,
5*95d28233SJohn Marino    2009, 2010, 2011, 2013 Free Software Foundation, Inc.
6e4b17023SJohn Marino    Contributed by Jason Merrill (jason@cygnus.com).
7e4b17023SJohn Marino 
8e4b17023SJohn Marino This file is part of GCC.
9e4b17023SJohn Marino 
10e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
11e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
12e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
13e4b17023SJohn Marino version.
14e4b17023SJohn Marino 
15e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
17e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18e4b17023SJohn Marino for more details.
19e4b17023SJohn Marino 
20e4b17023SJohn Marino You should have received a copy of the GNU General Public License
21e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
22e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
23e4b17023SJohn Marino 
24e4b17023SJohn Marino #include "config.h"
25e4b17023SJohn Marino #include "system.h"
26e4b17023SJohn Marino #include "coretypes.h"
27e4b17023SJohn Marino #include "tm.h"
28e4b17023SJohn Marino #include "intl.h"
29e4b17023SJohn Marino #include "obstack.h"
30e4b17023SJohn Marino #include "hashtab.h"
31e4b17023SJohn Marino #include "demangle.h"
32e4b17023SJohn Marino #include "collect2.h"
33e4b17023SJohn Marino #include "filenames.h"
34e4b17023SJohn Marino #include "diagnostic-core.h"
35e4b17023SJohn Marino #include "vec.h"
36e4b17023SJohn Marino 
37e4b17023SJohn Marino /* TARGET_64BIT may be defined to use driver specific functionality. */
38e4b17023SJohn Marino #undef TARGET_64BIT
39e4b17023SJohn Marino #define TARGET_64BIT TARGET_64BIT_DEFAULT
40e4b17023SJohn Marino 
41e4b17023SJohn Marino #define MAX_ITERATIONS 17
42e4b17023SJohn Marino 
43e4b17023SJohn Marino /* Defined in the automatically-generated underscore.c.  */
44e4b17023SJohn Marino extern int prepends_underscore;
45e4b17023SJohn Marino 
46e4b17023SJohn Marino static int tlink_verbose;
47e4b17023SJohn Marino 
48e4b17023SJohn Marino static char *initial_cwd;
49e4b17023SJohn Marino 
50e4b17023SJohn Marino /* Hash table boilerplate for working with htab_t.  We have hash tables
51e4b17023SJohn Marino    for symbol names, file names, and demangled symbols.  */
52e4b17023SJohn Marino 
53e4b17023SJohn Marino typedef struct symbol_hash_entry
54e4b17023SJohn Marino {
55e4b17023SJohn Marino   const char *key;
56e4b17023SJohn Marino   struct file_hash_entry *file;
57e4b17023SJohn Marino   int chosen;
58e4b17023SJohn Marino   int tweaking;
59e4b17023SJohn Marino   int tweaked;
60e4b17023SJohn Marino } symbol;
61e4b17023SJohn Marino 
62e4b17023SJohn Marino typedef struct file_hash_entry
63e4b17023SJohn Marino {
64e4b17023SJohn Marino   const char *key;
65e4b17023SJohn Marino   const char *args;
66e4b17023SJohn Marino   const char *dir;
67e4b17023SJohn Marino   const char *main;
68e4b17023SJohn Marino   int tweaking;
69e4b17023SJohn Marino } file;
70e4b17023SJohn Marino 
71e4b17023SJohn Marino typedef const char *str;
72e4b17023SJohn Marino DEF_VEC_P(str);
73e4b17023SJohn Marino DEF_VEC_ALLOC_P(str,heap);
74e4b17023SJohn Marino 
75e4b17023SJohn Marino typedef struct demangled_hash_entry
76e4b17023SJohn Marino {
77e4b17023SJohn Marino   const char *key;
78e4b17023SJohn Marino   VEC(str,heap) *mangled;
79e4b17023SJohn Marino } demangled;
80e4b17023SJohn Marino 
81e4b17023SJohn Marino /* Hash and comparison functions for these hash tables.  */
82e4b17023SJohn Marino 
83e4b17023SJohn Marino static int hash_string_eq (const void *, const void *);
84e4b17023SJohn Marino static hashval_t hash_string_hash (const void *);
85e4b17023SJohn Marino 
86e4b17023SJohn Marino static int
hash_string_eq(const void * s1_p,const void * s2_p)87e4b17023SJohn Marino hash_string_eq (const void *s1_p, const void *s2_p)
88e4b17023SJohn Marino {
89e4b17023SJohn Marino   const char *const *s1 = (const char *const *) s1_p;
90e4b17023SJohn Marino   const char *s2 = (const char *) s2_p;
91e4b17023SJohn Marino   return strcmp (*s1, s2) == 0;
92e4b17023SJohn Marino }
93e4b17023SJohn Marino 
94e4b17023SJohn Marino static hashval_t
hash_string_hash(const void * s_p)95e4b17023SJohn Marino hash_string_hash (const void *s_p)
96e4b17023SJohn Marino {
97e4b17023SJohn Marino   const char *const *s = (const char *const *) s_p;
98e4b17023SJohn Marino   return (*htab_hash_string) (*s);
99e4b17023SJohn Marino }
100e4b17023SJohn Marino 
101e4b17023SJohn Marino static htab_t symbol_table;
102e4b17023SJohn Marino 
103e4b17023SJohn Marino static struct symbol_hash_entry * symbol_hash_lookup (const char *, int);
104e4b17023SJohn Marino static struct file_hash_entry * file_hash_lookup (const char *);
105e4b17023SJohn Marino static struct demangled_hash_entry *demangled_hash_lookup (const char *, int);
106e4b17023SJohn Marino static void symbol_push (symbol *);
107e4b17023SJohn Marino static symbol * symbol_pop (void);
108e4b17023SJohn Marino static void file_push (file *);
109e4b17023SJohn Marino static file * file_pop (void);
110e4b17023SJohn Marino static void tlink_init (void);
111e4b17023SJohn Marino static int tlink_execute (const char *, char **, const char *, const char *);
112e4b17023SJohn Marino static char * frob_extension (const char *, const char *);
113e4b17023SJohn Marino static char * obstack_fgets (FILE *, struct obstack *);
114e4b17023SJohn Marino static char * tfgets (FILE *);
115e4b17023SJohn Marino static char * pfgets (FILE *);
116e4b17023SJohn Marino static void freadsym (FILE *, file *, int);
117e4b17023SJohn Marino static void read_repo_file (file *);
118e4b17023SJohn Marino static void maybe_tweak (char *, file *);
119e4b17023SJohn Marino static int recompile_files (void);
120e4b17023SJohn Marino static int read_repo_files (char **);
121e4b17023SJohn Marino static void demangle_new_symbols (void);
122e4b17023SJohn Marino static int scan_linker_output (const char *);
123e4b17023SJohn Marino 
124e4b17023SJohn Marino /* Look up an entry in the symbol hash table.  */
125e4b17023SJohn Marino 
126e4b17023SJohn Marino static struct symbol_hash_entry *
symbol_hash_lookup(const char * string,int create)127e4b17023SJohn Marino symbol_hash_lookup (const char *string, int create)
128e4b17023SJohn Marino {
129e4b17023SJohn Marino   void **e;
130e4b17023SJohn Marino   e = htab_find_slot_with_hash (symbol_table, string,
131e4b17023SJohn Marino 				(*htab_hash_string) (string),
132e4b17023SJohn Marino 				create ? INSERT : NO_INSERT);
133e4b17023SJohn Marino   if (e == NULL)
134e4b17023SJohn Marino     return NULL;
135e4b17023SJohn Marino   if (*e == NULL)
136e4b17023SJohn Marino     {
137e4b17023SJohn Marino       struct symbol_hash_entry *v;
138e4b17023SJohn Marino       *e = v = XCNEW (struct symbol_hash_entry);
139e4b17023SJohn Marino       v->key = xstrdup (string);
140e4b17023SJohn Marino     }
141e4b17023SJohn Marino   return (struct symbol_hash_entry *) *e;
142e4b17023SJohn Marino }
143e4b17023SJohn Marino 
144e4b17023SJohn Marino static htab_t file_table;
145e4b17023SJohn Marino 
146e4b17023SJohn Marino /* Look up an entry in the file hash table.  */
147e4b17023SJohn Marino 
148e4b17023SJohn Marino static struct file_hash_entry *
file_hash_lookup(const char * string)149e4b17023SJohn Marino file_hash_lookup (const char *string)
150e4b17023SJohn Marino {
151e4b17023SJohn Marino   void **e;
152e4b17023SJohn Marino   e = htab_find_slot_with_hash (file_table, string,
153e4b17023SJohn Marino 				(*htab_hash_string) (string),
154e4b17023SJohn Marino 				INSERT);
155e4b17023SJohn Marino   if (*e == NULL)
156e4b17023SJohn Marino     {
157e4b17023SJohn Marino       struct file_hash_entry *v;
158e4b17023SJohn Marino       *e = v = XCNEW (struct file_hash_entry);
159e4b17023SJohn Marino       v->key = xstrdup (string);
160e4b17023SJohn Marino     }
161e4b17023SJohn Marino   return (struct file_hash_entry *) *e;
162e4b17023SJohn Marino }
163e4b17023SJohn Marino 
164e4b17023SJohn Marino static htab_t demangled_table;
165e4b17023SJohn Marino 
166e4b17023SJohn Marino /* Look up an entry in the demangled name hash table.  */
167e4b17023SJohn Marino 
168e4b17023SJohn Marino static struct demangled_hash_entry *
demangled_hash_lookup(const char * string,int create)169e4b17023SJohn Marino demangled_hash_lookup (const char *string, int create)
170e4b17023SJohn Marino {
171e4b17023SJohn Marino   void **e;
172e4b17023SJohn Marino   e = htab_find_slot_with_hash (demangled_table, string,
173e4b17023SJohn Marino 				(*htab_hash_string) (string),
174e4b17023SJohn Marino 				create ? INSERT : NO_INSERT);
175e4b17023SJohn Marino   if (e == NULL)
176e4b17023SJohn Marino     return NULL;
177e4b17023SJohn Marino   if (*e == NULL)
178e4b17023SJohn Marino     {
179e4b17023SJohn Marino       struct demangled_hash_entry *v;
180e4b17023SJohn Marino       *e = v = XCNEW (struct demangled_hash_entry);
181e4b17023SJohn Marino       v->key = xstrdup (string);
182e4b17023SJohn Marino     }
183e4b17023SJohn Marino   return (struct demangled_hash_entry *) *e;
184e4b17023SJohn Marino }
185e4b17023SJohn Marino 
186e4b17023SJohn Marino /* Stack code.  */
187e4b17023SJohn Marino 
188e4b17023SJohn Marino struct symbol_stack_entry
189e4b17023SJohn Marino {
190e4b17023SJohn Marino   symbol *value;
191e4b17023SJohn Marino   struct symbol_stack_entry *next;
192e4b17023SJohn Marino };
193e4b17023SJohn Marino struct obstack symbol_stack_obstack;
194e4b17023SJohn Marino struct symbol_stack_entry *symbol_stack;
195e4b17023SJohn Marino 
196e4b17023SJohn Marino struct file_stack_entry
197e4b17023SJohn Marino {
198e4b17023SJohn Marino   file *value;
199e4b17023SJohn Marino   struct file_stack_entry *next;
200e4b17023SJohn Marino };
201e4b17023SJohn Marino struct obstack file_stack_obstack;
202e4b17023SJohn Marino struct file_stack_entry *file_stack;
203e4b17023SJohn Marino 
204e4b17023SJohn Marino static void
symbol_push(symbol * p)205e4b17023SJohn Marino symbol_push (symbol *p)
206e4b17023SJohn Marino {
207e4b17023SJohn Marino   struct symbol_stack_entry *ep
208e4b17023SJohn Marino     = XOBNEW (&symbol_stack_obstack, struct symbol_stack_entry);
209e4b17023SJohn Marino   ep->value = p;
210e4b17023SJohn Marino   ep->next = symbol_stack;
211e4b17023SJohn Marino   symbol_stack = ep;
212e4b17023SJohn Marino }
213e4b17023SJohn Marino 
214e4b17023SJohn Marino static symbol *
symbol_pop(void)215e4b17023SJohn Marino symbol_pop (void)
216e4b17023SJohn Marino {
217e4b17023SJohn Marino   struct symbol_stack_entry *ep = symbol_stack;
218e4b17023SJohn Marino   symbol *p;
219e4b17023SJohn Marino   if (ep == NULL)
220e4b17023SJohn Marino     return NULL;
221e4b17023SJohn Marino   p = ep->value;
222e4b17023SJohn Marino   symbol_stack = ep->next;
223e4b17023SJohn Marino   obstack_free (&symbol_stack_obstack, ep);
224e4b17023SJohn Marino   return p;
225e4b17023SJohn Marino }
226e4b17023SJohn Marino 
227e4b17023SJohn Marino static void
file_push(file * p)228e4b17023SJohn Marino file_push (file *p)
229e4b17023SJohn Marino {
230e4b17023SJohn Marino   struct file_stack_entry *ep;
231e4b17023SJohn Marino 
232e4b17023SJohn Marino   if (p->tweaking)
233e4b17023SJohn Marino     return;
234e4b17023SJohn Marino 
235e4b17023SJohn Marino   ep = XOBNEW (&file_stack_obstack, struct file_stack_entry);
236e4b17023SJohn Marino   ep->value = p;
237e4b17023SJohn Marino   ep->next = file_stack;
238e4b17023SJohn Marino   file_stack = ep;
239e4b17023SJohn Marino   p->tweaking = 1;
240e4b17023SJohn Marino }
241e4b17023SJohn Marino 
242e4b17023SJohn Marino static file *
file_pop(void)243e4b17023SJohn Marino file_pop (void)
244e4b17023SJohn Marino {
245e4b17023SJohn Marino   struct file_stack_entry *ep = file_stack;
246e4b17023SJohn Marino   file *p;
247e4b17023SJohn Marino   if (ep == NULL)
248e4b17023SJohn Marino     return NULL;
249e4b17023SJohn Marino   p = ep->value;
250e4b17023SJohn Marino   file_stack = ep->next;
251e4b17023SJohn Marino   obstack_free (&file_stack_obstack, ep);
252e4b17023SJohn Marino   p->tweaking = 0;
253e4b17023SJohn Marino   return p;
254e4b17023SJohn Marino }
255e4b17023SJohn Marino 
256e4b17023SJohn Marino /* Other machinery.  */
257e4b17023SJohn Marino 
258e4b17023SJohn Marino /* Initialize the tlink machinery.  Called from do_tlink.  */
259e4b17023SJohn Marino 
260e4b17023SJohn Marino static void
tlink_init(void)261e4b17023SJohn Marino tlink_init (void)
262e4b17023SJohn Marino {
263e4b17023SJohn Marino   const char *p;
264e4b17023SJohn Marino 
265e4b17023SJohn Marino   symbol_table = htab_create (500, hash_string_hash, hash_string_eq,
266e4b17023SJohn Marino 			      NULL);
267e4b17023SJohn Marino   file_table = htab_create (500, hash_string_hash, hash_string_eq,
268e4b17023SJohn Marino 			    NULL);
269e4b17023SJohn Marino   demangled_table = htab_create (500, hash_string_hash, hash_string_eq,
270e4b17023SJohn Marino 				 NULL);
271e4b17023SJohn Marino 
272e4b17023SJohn Marino   obstack_begin (&symbol_stack_obstack, 0);
273e4b17023SJohn Marino   obstack_begin (&file_stack_obstack, 0);
274e4b17023SJohn Marino 
275e4b17023SJohn Marino   p = getenv ("TLINK_VERBOSE");
276e4b17023SJohn Marino   if (p)
277e4b17023SJohn Marino     tlink_verbose = atoi (p);
278e4b17023SJohn Marino   else
279e4b17023SJohn Marino     {
280e4b17023SJohn Marino       tlink_verbose = 1;
281e4b17023SJohn Marino       if (vflag)
282e4b17023SJohn Marino 	tlink_verbose = 2;
283e4b17023SJohn Marino       if (debug)
284e4b17023SJohn Marino 	tlink_verbose = 3;
285e4b17023SJohn Marino     }
286e4b17023SJohn Marino 
287e4b17023SJohn Marino   initial_cwd = getpwd ();
288e4b17023SJohn Marino }
289e4b17023SJohn Marino 
290e4b17023SJohn Marino static int
tlink_execute(const char * prog,char ** argv,const char * outname,const char * errname)291e4b17023SJohn Marino tlink_execute (const char *prog, char **argv, const char *outname,
292e4b17023SJohn Marino 	       const char *errname)
293e4b17023SJohn Marino {
294e4b17023SJohn Marino   struct pex_obj *pex;
295e4b17023SJohn Marino 
296e4b17023SJohn Marino   pex = collect_execute (prog, argv, outname, errname, PEX_LAST | PEX_SEARCH);
297e4b17023SJohn Marino   return collect_wait (prog, pex);
298e4b17023SJohn Marino }
299e4b17023SJohn Marino 
300e4b17023SJohn Marino static char *
frob_extension(const char * s,const char * ext)301e4b17023SJohn Marino frob_extension (const char *s, const char *ext)
302e4b17023SJohn Marino {
303e4b17023SJohn Marino   const char *p;
304e4b17023SJohn Marino 
305e4b17023SJohn Marino   p = strrchr (lbasename (s), '.');
306e4b17023SJohn Marino   if (! p)
307e4b17023SJohn Marino     p = s + strlen (s);
308e4b17023SJohn Marino 
309e4b17023SJohn Marino   obstack_grow (&temporary_obstack, s, p - s);
310e4b17023SJohn Marino   return (char *) obstack_copy0 (&temporary_obstack, ext, strlen (ext));
311e4b17023SJohn Marino }
312e4b17023SJohn Marino 
313e4b17023SJohn Marino static char *
obstack_fgets(FILE * stream,struct obstack * ob)314e4b17023SJohn Marino obstack_fgets (FILE *stream, struct obstack *ob)
315e4b17023SJohn Marino {
316e4b17023SJohn Marino   int c;
317e4b17023SJohn Marino   while ((c = getc (stream)) != EOF && c != '\n')
318e4b17023SJohn Marino     obstack_1grow (ob, c);
319e4b17023SJohn Marino   if (obstack_object_size (ob) == 0)
320e4b17023SJohn Marino     return NULL;
321e4b17023SJohn Marino   obstack_1grow (ob, '\0');
322e4b17023SJohn Marino   return XOBFINISH (ob, char *);
323e4b17023SJohn Marino }
324e4b17023SJohn Marino 
325e4b17023SJohn Marino static char *
tfgets(FILE * stream)326e4b17023SJohn Marino tfgets (FILE *stream)
327e4b17023SJohn Marino {
328e4b17023SJohn Marino   return obstack_fgets (stream, &temporary_obstack);
329e4b17023SJohn Marino }
330e4b17023SJohn Marino 
331e4b17023SJohn Marino static char *
pfgets(FILE * stream)332e4b17023SJohn Marino pfgets (FILE *stream)
333e4b17023SJohn Marino {
334e4b17023SJohn Marino   return xstrdup (tfgets (stream));
335e4b17023SJohn Marino }
336e4b17023SJohn Marino 
337e4b17023SJohn Marino /* Real tlink code.  */
338e4b17023SJohn Marino 
339e4b17023SJohn Marino /* Subroutine of read_repo_file.  We are reading the repo file for file F,
340e4b17023SJohn Marino    which is coming in on STREAM, and the symbol that comes next in STREAM
341e4b17023SJohn Marino    is offered, chosen or provided if CHOSEN is 0, 1 or 2, respectively.
342e4b17023SJohn Marino 
343e4b17023SJohn Marino    XXX "provided" is unimplemented, both here and in the compiler.  */
344e4b17023SJohn Marino 
345e4b17023SJohn Marino static void
freadsym(FILE * stream,file * f,int chosen)346e4b17023SJohn Marino freadsym (FILE *stream, file *f, int chosen)
347e4b17023SJohn Marino {
348e4b17023SJohn Marino   symbol *sym;
349e4b17023SJohn Marino 
350e4b17023SJohn Marino   {
351e4b17023SJohn Marino     const char *name = tfgets (stream);
352e4b17023SJohn Marino     sym = symbol_hash_lookup (name, true);
353e4b17023SJohn Marino   }
354e4b17023SJohn Marino 
355e4b17023SJohn Marino   if (sym->file == NULL)
356e4b17023SJohn Marino     {
357e4b17023SJohn Marino       /* We didn't have this symbol already, so we choose this file.  */
358e4b17023SJohn Marino 
359e4b17023SJohn Marino       symbol_push (sym);
360e4b17023SJohn Marino       sym->file = f;
361e4b17023SJohn Marino       sym->chosen = chosen;
362e4b17023SJohn Marino     }
363e4b17023SJohn Marino   else if (chosen)
364e4b17023SJohn Marino     {
365e4b17023SJohn Marino       /* We want this file; cast aside any pretender.  */
366e4b17023SJohn Marino 
367e4b17023SJohn Marino       if (sym->chosen && sym->file != f)
368e4b17023SJohn Marino 	{
369e4b17023SJohn Marino 	  if (sym->chosen == 1)
370e4b17023SJohn Marino 	    file_push (sym->file);
371e4b17023SJohn Marino 	  else
372e4b17023SJohn Marino 	    {
373e4b17023SJohn Marino 	      file_push (f);
374e4b17023SJohn Marino 	      f = sym->file;
375e4b17023SJohn Marino 	      chosen = sym->chosen;
376e4b17023SJohn Marino 	    }
377e4b17023SJohn Marino 	}
378e4b17023SJohn Marino       sym->file = f;
379e4b17023SJohn Marino       sym->chosen = chosen;
380e4b17023SJohn Marino     }
381e4b17023SJohn Marino }
382e4b17023SJohn Marino 
383e4b17023SJohn Marino /* Read in the repo file denoted by F, and record all its information.  */
384e4b17023SJohn Marino 
385e4b17023SJohn Marino static void
read_repo_file(file * f)386e4b17023SJohn Marino read_repo_file (file *f)
387e4b17023SJohn Marino {
388e4b17023SJohn Marino   char c;
389e4b17023SJohn Marino   FILE *stream = fopen (f->key, "r");
390e4b17023SJohn Marino 
391e4b17023SJohn Marino   if (tlink_verbose >= 2)
392e4b17023SJohn Marino     fprintf (stderr, _("collect: reading %s\n"), f->key);
393e4b17023SJohn Marino 
394e4b17023SJohn Marino   while (fscanf (stream, "%c ", &c) == 1)
395e4b17023SJohn Marino     {
396e4b17023SJohn Marino       switch (c)
397e4b17023SJohn Marino 	{
398e4b17023SJohn Marino 	case 'A':
399e4b17023SJohn Marino 	  f->args = pfgets (stream);
400e4b17023SJohn Marino 	  break;
401e4b17023SJohn Marino 	case 'D':
402e4b17023SJohn Marino 	  f->dir = pfgets (stream);
403e4b17023SJohn Marino 	  break;
404e4b17023SJohn Marino 	case 'M':
405e4b17023SJohn Marino 	  f->main = pfgets (stream);
406e4b17023SJohn Marino 	  break;
407e4b17023SJohn Marino 	case 'P':
408e4b17023SJohn Marino 	  freadsym (stream, f, 2);
409e4b17023SJohn Marino 	  break;
410e4b17023SJohn Marino 	case 'C':
411e4b17023SJohn Marino 	  freadsym (stream, f, 1);
412e4b17023SJohn Marino 	  break;
413e4b17023SJohn Marino 	case 'O':
414e4b17023SJohn Marino 	  freadsym (stream, f, 0);
415e4b17023SJohn Marino 	  break;
416e4b17023SJohn Marino 	}
417e4b17023SJohn Marino       obstack_free (&temporary_obstack, temporary_firstobj);
418e4b17023SJohn Marino     }
419e4b17023SJohn Marino   fclose (stream);
420e4b17023SJohn Marino   if (f->args == NULL)
421e4b17023SJohn Marino     f->args = getenv ("COLLECT_GCC_OPTIONS");
422e4b17023SJohn Marino   if (f->dir == NULL)
423e4b17023SJohn Marino     f->dir = ".";
424e4b17023SJohn Marino }
425e4b17023SJohn Marino 
426e4b17023SJohn Marino /* We might want to modify LINE, which is a symbol line from file F.  We do
427e4b17023SJohn Marino    this if either we saw an error message referring to the symbol in
428e4b17023SJohn Marino    question, or we have already allocated the symbol to another file and
429e4b17023SJohn Marino    this one wants to emit it as well.  */
430e4b17023SJohn Marino 
431e4b17023SJohn Marino static void
maybe_tweak(char * line,file * f)432e4b17023SJohn Marino maybe_tweak (char *line, file *f)
433e4b17023SJohn Marino {
434e4b17023SJohn Marino   symbol *sym = symbol_hash_lookup (line + 2, false);
435e4b17023SJohn Marino 
436e4b17023SJohn Marino   if ((sym->file == f && sym->tweaking)
437e4b17023SJohn Marino       || (sym->file != f && line[0] == 'C'))
438e4b17023SJohn Marino     {
439e4b17023SJohn Marino       sym->tweaking = 0;
440e4b17023SJohn Marino       sym->tweaked = 1;
441e4b17023SJohn Marino 
442e4b17023SJohn Marino       if (line[0] == 'O')
443e4b17023SJohn Marino 	{
444e4b17023SJohn Marino 	  line[0] = 'C';
445e4b17023SJohn Marino 	  sym->chosen = 1;
446e4b17023SJohn Marino 	}
447e4b17023SJohn Marino       else
448e4b17023SJohn Marino 	{
449e4b17023SJohn Marino 	  line[0] = 'O';
450e4b17023SJohn Marino 	  sym->chosen = 0;
451e4b17023SJohn Marino 	}
452e4b17023SJohn Marino     }
453e4b17023SJohn Marino }
454e4b17023SJohn Marino 
455e4b17023SJohn Marino /* Update the repo files for each of the object files we have adjusted and
456e4b17023SJohn Marino    recompile.  */
457e4b17023SJohn Marino 
458e4b17023SJohn Marino static int
recompile_files(void)459e4b17023SJohn Marino recompile_files (void)
460e4b17023SJohn Marino {
461e4b17023SJohn Marino   file *f;
462e4b17023SJohn Marino 
463e4b17023SJohn Marino   putenv (xstrdup ("COMPILER_PATH="));
464e4b17023SJohn Marino   putenv (xstrdup ("LIBRARY_PATH="));
465e4b17023SJohn Marino 
466e4b17023SJohn Marino   while ((f = file_pop ()) != NULL)
467e4b17023SJohn Marino     {
468e4b17023SJohn Marino       char *line;
469e4b17023SJohn Marino       const char *p, *q;
470e4b17023SJohn Marino       char **argv;
471e4b17023SJohn Marino       struct obstack arg_stack;
472e4b17023SJohn Marino       FILE *stream = fopen (f->key, "r");
473e4b17023SJohn Marino       const char *const outname = frob_extension (f->key, ".rnw");
474e4b17023SJohn Marino       FILE *output = fopen (outname, "w");
475e4b17023SJohn Marino 
476e4b17023SJohn Marino       while ((line = tfgets (stream)) != NULL)
477e4b17023SJohn Marino 	{
478e4b17023SJohn Marino 	  switch (line[0])
479e4b17023SJohn Marino 	    {
480e4b17023SJohn Marino 	    case 'C':
481e4b17023SJohn Marino 	    case 'O':
482e4b17023SJohn Marino 	      maybe_tweak (line, f);
483e4b17023SJohn Marino 	    }
484e4b17023SJohn Marino 	  fprintf (output, "%s\n", line);
485e4b17023SJohn Marino 	}
486e4b17023SJohn Marino       fclose (stream);
487e4b17023SJohn Marino       fclose (output);
488e4b17023SJohn Marino       /* On Windows "rename" returns -1 and sets ERRNO to EACCESS if
489e4b17023SJohn Marino 	 the new file name already exists.  Therefore, we explicitly
490e4b17023SJohn Marino 	 remove the old file first.  */
491e4b17023SJohn Marino       if (remove (f->key) == -1)
492e4b17023SJohn Marino 	fatal_error ("removing .rpo file: %m");
493e4b17023SJohn Marino       if (rename (outname, f->key) == -1)
494e4b17023SJohn Marino 	fatal_error ("renaming .rpo file: %m");
495e4b17023SJohn Marino 
496e4b17023SJohn Marino       if (!f->args)
497e4b17023SJohn Marino 	{
498e4b17023SJohn Marino 	  error ("repository file '%s' does not contain command-line "
499e4b17023SJohn Marino 		 "arguments", f->key);
500e4b17023SJohn Marino 	  return 0;
501e4b17023SJohn Marino 	}
502e4b17023SJohn Marino 
503e4b17023SJohn Marino       /* Build a null-terminated argv array suitable for
504e4b17023SJohn Marino 	 tlink_execute().  Manipulate arguments on the arg_stack while
505e4b17023SJohn Marino 	 building argv on the temporary_obstack.  */
506e4b17023SJohn Marino 
507e4b17023SJohn Marino       obstack_init (&arg_stack);
508e4b17023SJohn Marino       obstack_ptr_grow (&temporary_obstack, c_file_name);
509e4b17023SJohn Marino 
510e4b17023SJohn Marino       for (p = f->args; *p != '\0'; p = q + 1)
511e4b17023SJohn Marino 	{
512e4b17023SJohn Marino 	  /* Arguments are delimited by single-quotes.  Find the
513e4b17023SJohn Marino 	     opening quote.  */
514e4b17023SJohn Marino 	  p = strchr (p, '\'');
515e4b17023SJohn Marino 	  if (!p)
516e4b17023SJohn Marino 	    goto done;
517e4b17023SJohn Marino 
518e4b17023SJohn Marino 	  /* Find the closing quote.  */
519e4b17023SJohn Marino 	  q = strchr (p + 1, '\'');
520e4b17023SJohn Marino 	  if (!q)
521e4b17023SJohn Marino 	    goto done;
522e4b17023SJohn Marino 
523e4b17023SJohn Marino 	  obstack_grow (&arg_stack, p + 1, q - (p + 1));
524e4b17023SJohn Marino 
525e4b17023SJohn Marino 	  /* Replace '\'' with '.  This is how set_collect_gcc_options
526e4b17023SJohn Marino 	     encodes a single-quote.  */
527e4b17023SJohn Marino 	  while (q[1] == '\\' && q[2] == '\'' && q[3] == '\'')
528e4b17023SJohn Marino 	    {
529e4b17023SJohn Marino 	      const char *r;
530e4b17023SJohn Marino 
531e4b17023SJohn Marino 	      r = strchr (q + 4, '\'');
532e4b17023SJohn Marino 	      if (!r)
533e4b17023SJohn Marino 		goto done;
534e4b17023SJohn Marino 
535e4b17023SJohn Marino 	      obstack_grow (&arg_stack, q + 3, r - (q + 3));
536e4b17023SJohn Marino 	      q = r;
537e4b17023SJohn Marino 	    }
538e4b17023SJohn Marino 
539e4b17023SJohn Marino 	  obstack_1grow (&arg_stack, '\0');
540e4b17023SJohn Marino 	  obstack_ptr_grow (&temporary_obstack, obstack_finish (&arg_stack));
541e4b17023SJohn Marino 	}
542e4b17023SJohn Marino     done:
543e4b17023SJohn Marino       obstack_ptr_grow (&temporary_obstack, f->main);
544e4b17023SJohn Marino       obstack_ptr_grow (&temporary_obstack, NULL);
545e4b17023SJohn Marino       argv = XOBFINISH (&temporary_obstack, char **);
546e4b17023SJohn Marino 
547e4b17023SJohn Marino       if (tlink_verbose)
548e4b17023SJohn Marino 	fprintf (stderr, _("collect: recompiling %s\n"), f->main);
549e4b17023SJohn Marino 
550e4b17023SJohn Marino       if (chdir (f->dir) != 0
551e4b17023SJohn Marino 	  || tlink_execute (c_file_name, argv, NULL, NULL) != 0
552e4b17023SJohn Marino 	  || chdir (initial_cwd) != 0)
553e4b17023SJohn Marino 	return 0;
554e4b17023SJohn Marino 
555e4b17023SJohn Marino       read_repo_file (f);
556e4b17023SJohn Marino 
557e4b17023SJohn Marino       obstack_free (&arg_stack, NULL);
558e4b17023SJohn Marino       obstack_free (&temporary_obstack, temporary_firstobj);
559e4b17023SJohn Marino     }
560e4b17023SJohn Marino   return 1;
561e4b17023SJohn Marino }
562e4b17023SJohn Marino 
563e4b17023SJohn Marino /* The first phase of processing: determine which object files have
564e4b17023SJohn Marino    .rpo files associated with them, and read in the information.  */
565e4b17023SJohn Marino 
566e4b17023SJohn Marino static int
read_repo_files(char ** object_lst)567e4b17023SJohn Marino read_repo_files (char **object_lst)
568e4b17023SJohn Marino {
569e4b17023SJohn Marino   char **object = object_lst;
570e4b17023SJohn Marino 
571e4b17023SJohn Marino   for (; *object; object++)
572e4b17023SJohn Marino     {
573e4b17023SJohn Marino       const char *p;
574e4b17023SJohn Marino       file *f;
575e4b17023SJohn Marino 
576e4b17023SJohn Marino       /* Don't bother trying for ld flags.  */
577e4b17023SJohn Marino       if (*object[0] == '-')
578e4b17023SJohn Marino 	continue;
579e4b17023SJohn Marino 
580e4b17023SJohn Marino       p = frob_extension (*object, ".rpo");
581e4b17023SJohn Marino 
582e4b17023SJohn Marino       if (! file_exists (p))
583e4b17023SJohn Marino 	continue;
584e4b17023SJohn Marino 
585e4b17023SJohn Marino       f = file_hash_lookup (p);
586e4b17023SJohn Marino 
587e4b17023SJohn Marino       read_repo_file (f);
588e4b17023SJohn Marino     }
589e4b17023SJohn Marino 
590e4b17023SJohn Marino   if (file_stack != NULL && ! recompile_files ())
591e4b17023SJohn Marino     return 0;
592e4b17023SJohn Marino 
593e4b17023SJohn Marino   return (symbol_stack != NULL);
594e4b17023SJohn Marino }
595e4b17023SJohn Marino 
596e4b17023SJohn Marino /* Add the demangled forms of any new symbols to the hash table.  */
597e4b17023SJohn Marino 
598e4b17023SJohn Marino static void
demangle_new_symbols(void)599e4b17023SJohn Marino demangle_new_symbols (void)
600e4b17023SJohn Marino {
601e4b17023SJohn Marino   symbol *sym;
602e4b17023SJohn Marino 
603e4b17023SJohn Marino   while ((sym = symbol_pop ()) != NULL)
604e4b17023SJohn Marino     {
605e4b17023SJohn Marino       demangled *dem;
606e4b17023SJohn Marino       const char *p = cplus_demangle (sym->key, DMGL_PARAMS | DMGL_ANSI);
607e4b17023SJohn Marino 
608e4b17023SJohn Marino       if (! p)
609e4b17023SJohn Marino 	continue;
610e4b17023SJohn Marino 
611e4b17023SJohn Marino       dem = demangled_hash_lookup (p, true);
612e4b17023SJohn Marino       VEC_safe_push (str, heap, dem->mangled, sym->key);
613e4b17023SJohn Marino     }
614e4b17023SJohn Marino }
615e4b17023SJohn Marino 
616e4b17023SJohn Marino /* We want to tweak symbol SYM.  Return true if all is well, false on
617e4b17023SJohn Marino    error.  */
618e4b17023SJohn Marino 
619e4b17023SJohn Marino static bool
start_tweaking(symbol * sym)620e4b17023SJohn Marino start_tweaking (symbol *sym)
621e4b17023SJohn Marino {
622e4b17023SJohn Marino   if (sym && sym->tweaked)
623e4b17023SJohn Marino     {
624e4b17023SJohn Marino       error ("'%s' was assigned to '%s', but was not defined "
625e4b17023SJohn Marino 	     "during recompilation, or vice versa",
626e4b17023SJohn Marino 	     sym->key, sym->file->key);
627e4b17023SJohn Marino       return 0;
628e4b17023SJohn Marino     }
629e4b17023SJohn Marino   if (sym && !sym->tweaking)
630e4b17023SJohn Marino     {
631e4b17023SJohn Marino       if (tlink_verbose >= 2)
632e4b17023SJohn Marino 	fprintf (stderr, _("collect: tweaking %s in %s\n"),
633e4b17023SJohn Marino 		 sym->key, sym->file->key);
634e4b17023SJohn Marino       sym->tweaking = 1;
635e4b17023SJohn Marino       file_push (sym->file);
636e4b17023SJohn Marino     }
637e4b17023SJohn Marino   return true;
638e4b17023SJohn Marino }
639e4b17023SJohn Marino 
640e4b17023SJohn Marino /* Step through the output of the linker, in the file named FNAME, and
641e4b17023SJohn Marino    adjust the settings for each symbol encountered.  */
642e4b17023SJohn Marino 
643e4b17023SJohn Marino static int
scan_linker_output(const char * fname)644e4b17023SJohn Marino scan_linker_output (const char *fname)
645e4b17023SJohn Marino {
646e4b17023SJohn Marino   FILE *stream = fopen (fname, "r");
647e4b17023SJohn Marino   char *line;
648e4b17023SJohn Marino   int skip_next_in_line = 0;
649e4b17023SJohn Marino 
650e4b17023SJohn Marino   while ((line = tfgets (stream)) != NULL)
651e4b17023SJohn Marino     {
652e4b17023SJohn Marino       char *p = line, *q;
653e4b17023SJohn Marino       symbol *sym;
654e4b17023SJohn Marino       demangled *dem = 0;
655e4b17023SJohn Marino       int end;
656e4b17023SJohn Marino       int ok = 0;
657e4b17023SJohn Marino       unsigned ix;
658e4b17023SJohn Marino       str s;
659e4b17023SJohn Marino 
660e4b17023SJohn Marino       /* On darwin9, we might have to skip " in " lines as well.  */
661e4b17023SJohn Marino       if (skip_next_in_line
662e4b17023SJohn Marino 	  && strstr (p, " in "))
663e4b17023SJohn Marino 	  continue;
664e4b17023SJohn Marino       skip_next_in_line = 0;
665e4b17023SJohn Marino 
666e4b17023SJohn Marino       while (*p && ISSPACE ((unsigned char) *p))
667e4b17023SJohn Marino 	++p;
668e4b17023SJohn Marino 
669e4b17023SJohn Marino       if (! *p)
670e4b17023SJohn Marino 	continue;
671e4b17023SJohn Marino 
672e4b17023SJohn Marino       for (q = p; *q && ! ISSPACE ((unsigned char) *q); ++q)
673e4b17023SJohn Marino 	;
674e4b17023SJohn Marino 
675e4b17023SJohn Marino       /* Try the first word on the line.  */
676e4b17023SJohn Marino       if (*p == '.')
677e4b17023SJohn Marino 	++p;
678e4b17023SJohn Marino       if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)))
679e4b17023SJohn Marino 	p += strlen (USER_LABEL_PREFIX);
680e4b17023SJohn Marino 
681e4b17023SJohn Marino       end = ! *q;
682e4b17023SJohn Marino       *q = 0;
683e4b17023SJohn Marino       sym = symbol_hash_lookup (p, false);
684e4b17023SJohn Marino 
685e4b17023SJohn Marino       /* Some SVR4 linkers produce messages like
686e4b17023SJohn Marino 	 ld: 0711-317 ERROR: Undefined symbol: .g__t3foo1Zi
687e4b17023SJohn Marino 	 */
688e4b17023SJohn Marino       if (! sym && ! end && strstr (q + 1, "Undefined symbol: "))
689e4b17023SJohn Marino 	{
690e4b17023SJohn Marino 	  char *p = strrchr (q + 1, ' ');
691e4b17023SJohn Marino 	  p++;
692e4b17023SJohn Marino 	  if (*p == '.')
693e4b17023SJohn Marino 	    p++;
694e4b17023SJohn Marino 	  if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)))
695e4b17023SJohn Marino 	    p += strlen (USER_LABEL_PREFIX);
696e4b17023SJohn Marino 	  sym = symbol_hash_lookup (p, false);
697e4b17023SJohn Marino 	}
698e4b17023SJohn Marino 
699e4b17023SJohn Marino       if (! sym && ! end)
700e4b17023SJohn Marino 	/* Try a mangled name in quotes.  */
701e4b17023SJohn Marino 	{
702e4b17023SJohn Marino 	  char *oldq = q + 1;
703e4b17023SJohn Marino 	  q = 0;
704e4b17023SJohn Marino 
705e4b17023SJohn Marino 	  /* On darwin9, we look for "foo" referenced from:\n\(.* in .*\n\)*  */
706e4b17023SJohn Marino 	  if (strcmp (oldq, "referenced from:") == 0)
707e4b17023SJohn Marino 	    {
708e4b17023SJohn Marino 	      /* We have to remember that we found a symbol to tweak.  */
709e4b17023SJohn Marino 	      ok = 1;
710e4b17023SJohn Marino 
711e4b17023SJohn Marino 	      /* We actually want to start from the first word on the
712e4b17023SJohn Marino 		 line.  */
713e4b17023SJohn Marino 	      oldq = p;
714e4b17023SJohn Marino 
715e4b17023SJohn Marino 	      /* Since the format is multiline, we have to skip
716e4b17023SJohn Marino 		 following lines with " in ".  */
717e4b17023SJohn Marino 	      skip_next_in_line = 1;
718e4b17023SJohn Marino 	    }
719e4b17023SJohn Marino 
720e4b17023SJohn Marino 	  /* First try `GNU style'.  */
721e4b17023SJohn Marino 	  p = strchr (oldq, '`');
722e4b17023SJohn Marino 	  if (p)
723e4b17023SJohn Marino 	    p++, q = strchr (p, '\'');
724e4b17023SJohn Marino 	  /* Then try "double quotes".  */
725e4b17023SJohn Marino 	  else if (p = strchr (oldq, '"'), p)
726e4b17023SJohn Marino 	    p++, q = strchr (p, '"');
727e4b17023SJohn Marino 	  /* Then try 'single quotes'.  */
728e4b17023SJohn Marino 	  else if (p = strchr (oldq, '\''), p)
729e4b17023SJohn Marino 	    p++, q = strchr (p, '\'');
730e4b17023SJohn Marino 	  else {
731e4b17023SJohn Marino 	    /* Then try entire line.  */
732e4b17023SJohn Marino 	    q = strchr (oldq, 0);
733e4b17023SJohn Marino 	    if (q != oldq)
734e4b17023SJohn Marino 	      p = (char *)oldq;
735e4b17023SJohn Marino 	  }
736e4b17023SJohn Marino 
737e4b17023SJohn Marino 	  if (p)
738e4b17023SJohn Marino 	    {
739e4b17023SJohn Marino 	      /* Don't let the strstr's below see the demangled name; we
740e4b17023SJohn Marino 		 might get spurious matches.  */
741e4b17023SJohn Marino 	      p[-1] = '\0';
742e4b17023SJohn Marino 
743e4b17023SJohn Marino 	      /* powerpc64-linux references .foo when calling function foo.  */
744e4b17023SJohn Marino 	      if (*p == '.')
745e4b17023SJohn Marino 		p++;
746e4b17023SJohn Marino 	    }
747e4b17023SJohn Marino 
748e4b17023SJohn Marino 	  /* We need to check for certain error keywords here, or we would
749e4b17023SJohn Marino 	     mistakenly use GNU ld's "In function `foo':" message.  */
750e4b17023SJohn Marino 	  if (q && (ok
751e4b17023SJohn Marino 		    || strstr (oldq, "ndefined")
752e4b17023SJohn Marino 		    || strstr (oldq, "nresolved")
753e4b17023SJohn Marino 		    || strstr (oldq, "nsatisfied")
754e4b17023SJohn Marino 		    || strstr (oldq, "ultiple")))
755e4b17023SJohn Marino 	    {
756e4b17023SJohn Marino 	      *q = 0;
757e4b17023SJohn Marino 	      dem = demangled_hash_lookup (p, false);
758e4b17023SJohn Marino 	      if (!dem)
759e4b17023SJohn Marino 		{
760e4b17023SJohn Marino 		  if (!strncmp (p, USER_LABEL_PREFIX,
761e4b17023SJohn Marino 				strlen (USER_LABEL_PREFIX)))
762e4b17023SJohn Marino 		    p += strlen (USER_LABEL_PREFIX);
763e4b17023SJohn Marino 		  sym = symbol_hash_lookup (p, false);
764e4b17023SJohn Marino 		}
765e4b17023SJohn Marino 	    }
766e4b17023SJohn Marino 	}
767e4b17023SJohn Marino 
768e4b17023SJohn Marino       if (dem)
769e4b17023SJohn Marino 	{
770e4b17023SJohn Marino 	  /* We found a demangled name.  If this is the name of a
771e4b17023SJohn Marino 	     constructor or destructor, there can be several mangled names
772e4b17023SJohn Marino 	     that match it, so choose or unchoose all of them.  If some are
773e4b17023SJohn Marino 	     chosen and some not, leave the later ones that don't match
774e4b17023SJohn Marino 	     alone for now; either this will cause the link to suceed, or
775e4b17023SJohn Marino 	     on the next attempt we will switch all of them the other way
776e4b17023SJohn Marino 	     and that will cause it to succeed.  */
777e4b17023SJohn Marino 	  int chosen = 0;
778e4b17023SJohn Marino 	  int len = VEC_length (str, dem->mangled);
779e4b17023SJohn Marino 	  ok = true;
780e4b17023SJohn Marino 	  FOR_EACH_VEC_ELT (str, dem->mangled, ix, s)
781e4b17023SJohn Marino 	    {
782e4b17023SJohn Marino 	      sym = symbol_hash_lookup (s, false);
783e4b17023SJohn Marino 	      if (ix == 0)
784e4b17023SJohn Marino 		chosen = sym->chosen;
785e4b17023SJohn Marino 	      else if (sym->chosen != chosen)
786e4b17023SJohn Marino 		/* Mismatch.  */
787e4b17023SJohn Marino 		continue;
788e4b17023SJohn Marino 	      /* Avoid an error about re-tweaking when we guess wrong in
789e4b17023SJohn Marino 		 the case of mismatch.  */
790e4b17023SJohn Marino 	      if (len > 1)
791e4b17023SJohn Marino 		sym->tweaked = false;
792e4b17023SJohn Marino 	      ok = start_tweaking (sym);
793e4b17023SJohn Marino 	    }
794e4b17023SJohn Marino 	}
795e4b17023SJohn Marino       else
796e4b17023SJohn Marino 	ok = start_tweaking (sym);
797e4b17023SJohn Marino 
798e4b17023SJohn Marino       obstack_free (&temporary_obstack, temporary_firstobj);
799e4b17023SJohn Marino 
800e4b17023SJohn Marino       if (!ok)
801e4b17023SJohn Marino 	{
802e4b17023SJohn Marino 	  fclose (stream);
803e4b17023SJohn Marino 	  return 0;
804e4b17023SJohn Marino 	}
805e4b17023SJohn Marino     }
806e4b17023SJohn Marino 
807e4b17023SJohn Marino   fclose (stream);
808e4b17023SJohn Marino   return (file_stack != NULL);
809e4b17023SJohn Marino }
810e4b17023SJohn Marino 
811e4b17023SJohn Marino /* Entry point for tlink.  Called from main in collect2.c.
812e4b17023SJohn Marino 
813e4b17023SJohn Marino    Iteratively try to provide definitions for all the unresolved symbols
814e4b17023SJohn Marino    mentioned in the linker error messages.
815e4b17023SJohn Marino 
816e4b17023SJohn Marino    LD_ARGV is an array of arguments for the linker.
817e4b17023SJohn Marino    OBJECT_LST is an array of object files that we may be able to recompile
818e4b17023SJohn Marino      to provide missing definitions.  Currently ignored.  */
819e4b17023SJohn Marino 
820e4b17023SJohn Marino void
do_tlink(char ** ld_argv,char ** object_lst ATTRIBUTE_UNUSED)821e4b17023SJohn Marino do_tlink (char **ld_argv, char **object_lst ATTRIBUTE_UNUSED)
822e4b17023SJohn Marino {
823*95d28233SJohn Marino   int ret = tlink_execute ("ld", ld_argv, ldout, lderrout);
824e4b17023SJohn Marino 
825e4b17023SJohn Marino   tlink_init ();
826e4b17023SJohn Marino 
827*95d28233SJohn Marino   if (ret)
828e4b17023SJohn Marino     {
829e4b17023SJohn Marino       int i = 0;
830e4b17023SJohn Marino 
831e4b17023SJohn Marino       /* Until collect does a better job of figuring out which are object
832e4b17023SJohn Marino 	 files, assume that everything on the command line could be.  */
833e4b17023SJohn Marino       if (read_repo_files (ld_argv))
834*95d28233SJohn Marino 	while (ret && i++ < MAX_ITERATIONS)
835e4b17023SJohn Marino 	  {
836e4b17023SJohn Marino 	    if (tlink_verbose >= 3)
837e4b17023SJohn Marino 	      {
838e4b17023SJohn Marino 		dump_file (ldout, stdout);
839e4b17023SJohn Marino 		dump_file (lderrout, stderr);
840e4b17023SJohn Marino 	      }
841e4b17023SJohn Marino 	    demangle_new_symbols ();
842e4b17023SJohn Marino 	    if (! scan_linker_output (ldout)
843e4b17023SJohn Marino 		&& ! scan_linker_output (lderrout))
844e4b17023SJohn Marino 	      break;
845e4b17023SJohn Marino 	    if (! recompile_files ())
846e4b17023SJohn Marino 	      break;
847e4b17023SJohn Marino 	    if (tlink_verbose)
848e4b17023SJohn Marino 	      fprintf (stderr, _("collect: relinking\n"));
849*95d28233SJohn Marino 	    ret = tlink_execute ("ld", ld_argv, ldout, lderrout);
850e4b17023SJohn Marino 	  }
851e4b17023SJohn Marino     }
852e4b17023SJohn Marino 
853e4b17023SJohn Marino   dump_file (ldout, stdout);
854e4b17023SJohn Marino   unlink (ldout);
855e4b17023SJohn Marino   dump_file (lderrout, stderr);
856e4b17023SJohn Marino   unlink (lderrout);
857*95d28233SJohn Marino   if (ret)
858e4b17023SJohn Marino     {
859*95d28233SJohn Marino       error ("ld returned %d exit status", ret);
860*95d28233SJohn Marino       exit (ret);
861e4b17023SJohn Marino     }
862e4b17023SJohn Marino }
863