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