Mercurial > hg > CbC > CbC_gcc
annotate gcc/tlink.c @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | a06113de4d67 |
children | b7f97abdc517 |
rev | line source |
---|---|
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 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
286 pex = collect_execute (prog, argv, outname, errname, PEX_LAST | PEX_SEARCH); |
0 | 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 " | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
732 "during recompilation, or vice versa", |
0 | 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 } |