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