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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [tlink.c] - Blame information for rev 14

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

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

powered by: WebSVN 2.1.0

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