OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [tlink.c] - Blame information for rev 433

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 280 jeremybenn
/* 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
/* TARGET_64BIT may be defined to use driver specific functionality. */
36
#undef TARGET_64BIT
37
#define TARGET_64BIT TARGET_64BIT_DEFAULT
38
 
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
 
290
  pex = collect_execute (prog, argv, outname, errname, PEX_LAST | PEX_SEARCH);
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 "
736
                 "during recompilation, or vice versa",
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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.