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