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

Subversion Repositories openrisc_me

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

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

Line No. Rev Author Line
1 38 julius
/* 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
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
 
34
#define MAX_ITERATIONS 17
35
 
36
/* Defined in the automatically-generated underscore.c.  */
37
extern int prepends_underscore;
38
 
39
static int tlink_verbose;
40
 
41
static char initial_cwd[MAXPATHLEN + 1];
42
 
43
/* Hash table boilerplate for working with htab_t.  We have hash tables
44
   for symbol names, file names, and demangled symbols.  */
45
 
46
typedef struct symbol_hash_entry
47
{
48
  const char *key;
49
  struct file_hash_entry *file;
50
  int chosen;
51
  int tweaking;
52
  int tweaked;
53
} symbol;
54
 
55
typedef struct file_hash_entry
56
{
57
  const char *key;
58
  const char *args;
59
  const char *dir;
60
  const char *main;
61
  int tweaking;
62
} file;
63
 
64
typedef struct demangled_hash_entry
65
{
66
  const char *key;
67
  const char *mangled;
68
} demangled;
69
 
70
/* Hash and comparison functions for these hash tables.  */
71
 
72
static int hash_string_eq (const void *, const void *);
73
static hashval_t hash_string_hash (const void *);
74
 
75
static int
76
hash_string_eq (const void *s1_p, const void *s2_p)
77
{
78
  const char *const *s1 = (const char *const *) s1_p;
79
  const char *s2 = (const char *) s2_p;
80
  return strcmp (*s1, s2) == 0;
81
}
82
 
83
static hashval_t
84
hash_string_hash (const void *s_p)
85
{
86
  const char *const *s = (const char *const *) s_p;
87
  return (*htab_hash_string) (*s);
88
}
89
 
90
static htab_t symbol_table;
91
 
92
static struct symbol_hash_entry * symbol_hash_lookup (const char *, int);
93
static struct file_hash_entry * file_hash_lookup (const char *);
94
static struct demangled_hash_entry *demangled_hash_lookup (const char *, int);
95
static void symbol_push (symbol *);
96
static symbol * symbol_pop (void);
97
static void file_push (file *);
98
static file * file_pop (void);
99
static void tlink_init (void);
100
static int tlink_execute (const char *, char **, const char *, const char *);
101
static char * frob_extension (const char *, const char *);
102
static char * obstack_fgets (FILE *, struct obstack *);
103
static char * tfgets (FILE *);
104
static char * pfgets (FILE *);
105
static void freadsym (FILE *, file *, int);
106
static void read_repo_file (file *);
107
static void maybe_tweak (char *, file *);
108
static int recompile_files (void);
109
static int read_repo_files (char **);
110
static void demangle_new_symbols (void);
111
static int scan_linker_output (const char *);
112
 
113
/* Look up an entry in the symbol hash table.  */
114
 
115
static struct symbol_hash_entry *
116
symbol_hash_lookup (const char *string, int create)
117
{
118
  void **e;
119
  e = htab_find_slot_with_hash (symbol_table, string,
120
                                (*htab_hash_string) (string),
121
                                create ? INSERT : NO_INSERT);
122
  if (e == NULL)
123
    return NULL;
124
  if (*e == NULL)
125
    {
126
      struct symbol_hash_entry *v;
127
      *e = v = XCNEW (struct symbol_hash_entry);
128
      v->key = xstrdup (string);
129
    }
130
  return *e;
131
}
132
 
133
static htab_t file_table;
134
 
135
/* Look up an entry in the file hash table.  */
136
 
137
static struct file_hash_entry *
138
file_hash_lookup (const char *string)
139
{
140
  void **e;
141
  e = htab_find_slot_with_hash (file_table, string,
142
                                (*htab_hash_string) (string),
143
                                INSERT);
144
  if (*e == NULL)
145
    {
146
      struct file_hash_entry *v;
147
      *e = v = XCNEW (struct file_hash_entry);
148
      v->key = xstrdup (string);
149
    }
150
  return *e;
151
}
152
 
153
static htab_t demangled_table;
154
 
155
/* Look up an entry in the demangled name hash table.  */
156
 
157
static struct demangled_hash_entry *
158
demangled_hash_lookup (const char *string, int create)
159
{
160
  void **e;
161
  e = htab_find_slot_with_hash (demangled_table, string,
162
                                (*htab_hash_string) (string),
163
                                create ? INSERT : NO_INSERT);
164
  if (e == NULL)
165
    return NULL;
166
  if (*e == NULL)
167
    {
168
      struct demangled_hash_entry *v;
169
      *e = v = XCNEW (struct demangled_hash_entry);
170
      v->key = xstrdup (string);
171
    }
172
  return *e;
173
}
174
 
175
/* Stack code.  */
176
 
177
struct symbol_stack_entry
178
{
179
  symbol *value;
180
  struct symbol_stack_entry *next;
181
};
182
struct obstack symbol_stack_obstack;
183
struct symbol_stack_entry *symbol_stack;
184
 
185
struct file_stack_entry
186
{
187
  file *value;
188
  struct file_stack_entry *next;
189
};
190
struct obstack file_stack_obstack;
191
struct file_stack_entry *file_stack;
192
 
193
static void
194
symbol_push (symbol *p)
195
{
196
  struct symbol_stack_entry *ep = obstack_alloc
197
    (&symbol_stack_obstack, sizeof (struct symbol_stack_entry));
198
  ep->value = p;
199
  ep->next = symbol_stack;
200
  symbol_stack = ep;
201
}
202
 
203
static symbol *
204
symbol_pop (void)
205
{
206
  struct symbol_stack_entry *ep = symbol_stack;
207
  symbol *p;
208
  if (ep == NULL)
209
    return NULL;
210
  p = ep->value;
211
  symbol_stack = ep->next;
212
  obstack_free (&symbol_stack_obstack, ep);
213
  return p;
214
}
215
 
216
static void
217
file_push (file *p)
218
{
219
  struct file_stack_entry *ep;
220
 
221
  if (p->tweaking)
222
    return;
223
 
224
  ep = obstack_alloc
225
    (&file_stack_obstack, sizeof (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
  getcwd (initial_cwd, sizeof (initial_cwd));
278
}
279
 
280
static int
281
tlink_execute (const char *prog, char **argv, const char *outname,
282
               const char *errname)
283
{
284
  struct pex_obj *pex;
285
 
286
  pex = collect_execute (prog, argv, outname, errname);
287
  return collect_wait (prog, pex);
288
}
289
 
290
static char *
291
frob_extension (const char *s, const char *ext)
292
{
293
  const char *p = strrchr (s, '/');
294
  if (! p)
295
    p = s;
296
  p = strrchr (p, '.');
297
  if (! p)
298
    p = s + strlen (s);
299
 
300
  obstack_grow (&temporary_obstack, s, p - s);
301
  return 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
          const 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
          else {
687
            /* Then try entire line.  */
688
            q = strchr (oldq, 0);
689
            if (q != oldq)
690
              p = (char *)oldq;
691
          }
692
 
693
          if (p)
694
            {
695
              /* Don't let the strstr's below see the demangled name; we
696
                 might get spurious matches.  */
697
              p[-1] = '\0';
698
 
699
              /* powerpc64-linux references .foo when calling function foo.  */
700
              if (*p == '.')
701
                p++;
702
            }
703
 
704
          /* We need to check for certain error keywords here, or we would
705
             mistakenly use GNU ld's "In function `foo':" message.  */
706
          if (q && (ok
707
                    || strstr (oldq, "ndefined")
708
                    || strstr (oldq, "nresolved")
709
                    || strstr (oldq, "nsatisfied")
710
                    || strstr (oldq, "ultiple")))
711
            {
712
              *q = 0;
713
              dem = demangled_hash_lookup (p, false);
714
              if (dem)
715
                sym = symbol_hash_lookup (dem->mangled, false);
716
              else
717
                {
718
                  if (!strncmp (p, USER_LABEL_PREFIX,
719
                                strlen (USER_LABEL_PREFIX)))
720
                    p += strlen (USER_LABEL_PREFIX);
721
                  sym = symbol_hash_lookup (p, false);
722
                }
723
            }
724
        }
725
 
726
      if (sym && sym->tweaked)
727
        {
728
          error ("'%s' was assigned to '%s', but was not defined "
729
                 "during recompilation, or vice versa",
730
                 sym->key, sym->file->key);
731
          fclose (stream);
732
          return 0;
733
        }
734
      if (sym && !sym->tweaking)
735
        {
736
          if (tlink_verbose >= 2)
737
            fprintf (stderr, _("collect: tweaking %s in %s\n"),
738
                     sym->key, sym->file->key);
739
          sym->tweaking = 1;
740
          file_push (sym->file);
741
        }
742
 
743
      obstack_free (&temporary_obstack, temporary_firstobj);
744
    }
745
 
746
  fclose (stream);
747
  return (file_stack != NULL);
748
}
749
 
750
/* Entry point for tlink.  Called from main in collect2.c.
751
 
752
   Iteratively try to provide definitions for all the unresolved symbols
753
   mentioned in the linker error messages.
754
 
755
   LD_ARGV is an array of arguments for the linker.
756
   OBJECT_LST is an array of object files that we may be able to recompile
757
     to provide missing definitions.  Currently ignored.  */
758
 
759
void
760
do_tlink (char **ld_argv, char **object_lst ATTRIBUTE_UNUSED)
761
{
762
  int exit = tlink_execute ("ld", ld_argv, ldout, lderrout);
763
 
764
  tlink_init ();
765
 
766
  if (exit)
767
    {
768
      int i = 0;
769
 
770
      /* Until collect does a better job of figuring out which are object
771
         files, assume that everything on the command line could be.  */
772
      if (read_repo_files (ld_argv))
773
        while (exit && i++ < MAX_ITERATIONS)
774
          {
775
            if (tlink_verbose >= 3)
776
              {
777
                dump_file (ldout, stdout);
778
                dump_file (lderrout, stderr);
779
              }
780
            demangle_new_symbols ();
781
            if (! scan_linker_output (ldout)
782
                && ! scan_linker_output (lderrout))
783
              break;
784
            if (! recompile_files ())
785
              break;
786
            if (tlink_verbose)
787
              fprintf (stderr, _("collect: relinking\n"));
788
            exit = tlink_execute ("ld", ld_argv, ldout, lderrout);
789
          }
790
    }
791
 
792
  dump_file (ldout, stdout);
793
  unlink (ldout);
794
  dump_file (lderrout, stderr);
795
  unlink (lderrout);
796
  if (exit)
797
    {
798
      error ("ld returned %d exit status", exit);
799
      collect_exit (exit);
800
    }
801
}

powered by: WebSVN 2.1.0

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