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