150397Sobrien/* Scan linker error messages for missing template instantiations and provide
250397Sobrien   them.
350397Sobrien
4169689Skan   Copyright (C) 1995, 1998, 1999, 2000, 2001, 2003, 2004, 2005
5132718Skan   Free Software Foundation, Inc.
650397Sobrien   Contributed by Jason Merrill (jason@cygnus.com).
750397Sobrien
890075SobrienThis file is part of GCC.
950397Sobrien
1090075SobrienGCC is free software; you can redistribute it and/or modify it under
1190075Sobrienthe terms of the GNU General Public License as published by the Free
1290075SobrienSoftware Foundation; either version 2, or (at your option) any later
1390075Sobrienversion.
1450397Sobrien
1590075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1690075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1790075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1890075Sobrienfor more details.
1950397Sobrien
2050397SobrienYou should have received a copy of the GNU General Public License
2190075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
22169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
23169689Skan02110-1301, USA.  */
2450397Sobrien
2550397Sobrien#include "config.h"
2650397Sobrien#include "system.h"
27132718Skan#include "coretypes.h"
28132718Skan#include "tm.h"
2990075Sobrien#include "intl.h"
30117395Skan#include "obstack.h"
31117395Skan#include "hashtab.h"
3250397Sobrien#include "demangle.h"
3352284Sobrien#include "collect2.h"
3450397Sobrien
3550397Sobrien#define MAX_ITERATIONS 17
3650397Sobrien
3750397Sobrien/* Defined in the automatically-generated underscore.c.  */
3850397Sobrienextern int prepends_underscore;
3950397Sobrien
4050397Sobrienstatic int tlink_verbose;
41169689Skan
42169689Skanstatic char initial_cwd[MAXPATHLEN + 1];
4350397Sobrien
44117395Skan/* Hash table boilerplate for working with htab_t.  We have hash tables
4552284Sobrien   for symbol names, file names, and demangled symbols.  */
4650397Sobrien
4750397Sobrientypedef struct symbol_hash_entry
4850397Sobrien{
49117395Skan  const char *key;
5050397Sobrien  struct file_hash_entry *file;
5150397Sobrien  int chosen;
5250397Sobrien  int tweaking;
5350397Sobrien  int tweaked;
5450397Sobrien} symbol;
5550397Sobrien
5650397Sobrientypedef struct file_hash_entry
5750397Sobrien{
58117395Skan  const char *key;
5950397Sobrien  const char *args;
6050397Sobrien  const char *dir;
6150397Sobrien  const char *main;
6250397Sobrien  int tweaking;
6350397Sobrien} file;
6450397Sobrien
6550397Sobrientypedef struct demangled_hash_entry
6650397Sobrien{
67117395Skan  const char *key;
6850397Sobrien  const char *mangled;
6950397Sobrien} demangled;
7050397Sobrien
71117395Skan/* Hash and comparison functions for these hash tables.  */
7250397Sobrien
73132718Skanstatic int hash_string_eq (const void *, const void *);
74132718Skanstatic hashval_t hash_string_hash (const void *);
75117395Skan
76117395Skanstatic int
77132718Skanhash_string_eq (const void *s1_p, const void *s2_p)
78117395Skan{
79117395Skan  const char *const *s1 = (const char *const *) s1_p;
80117395Skan  const char *s2 = (const char *) s2_p;
81117395Skan  return strcmp (*s1, s2) == 0;
82117395Skan}
83117395Skan
84117395Skanstatic hashval_t
85132718Skanhash_string_hash (const void *s_p)
86117395Skan{
87117395Skan  const char *const *s = (const char *const *) s_p;
88117395Skan  return (*htab_hash_string) (*s);
89117395Skan}
90117395Skan
91117395Skanstatic htab_t symbol_table;
92117395Skan
93132718Skanstatic struct symbol_hash_entry * symbol_hash_lookup (const char *, int);
94132718Skanstatic struct file_hash_entry * file_hash_lookup (const char *);
95132718Skanstatic struct demangled_hash_entry *demangled_hash_lookup (const char *, int);
96132718Skanstatic void symbol_push (symbol *);
97132718Skanstatic symbol * symbol_pop (void);
98132718Skanstatic void file_push (file *);
99132718Skanstatic file * file_pop (void);
100132718Skanstatic void tlink_init (void);
101169689Skanstatic int tlink_execute (const char *, char **, const char *, const char *);
102132718Skanstatic char * frob_extension (const char *, const char *);
103132718Skanstatic char * obstack_fgets (FILE *, struct obstack *);
104132718Skanstatic char * tfgets (FILE *);
105132718Skanstatic char * pfgets (FILE *);
106132718Skanstatic void freadsym (FILE *, file *, int);
107132718Skanstatic void read_repo_file (file *);
108132718Skanstatic void maybe_tweak (char *, file *);
109132718Skanstatic int recompile_files (void);
110132718Skanstatic int read_repo_files (char **);
111132718Skanstatic void demangle_new_symbols (void);
112132718Skanstatic int scan_linker_output (const char *);
11352284Sobrien
11452284Sobrien/* Look up an entry in the symbol hash table.  */
11552284Sobrien
11650397Sobrienstatic struct symbol_hash_entry *
117132718Skansymbol_hash_lookup (const char *string, int create)
11850397Sobrien{
119132718Skan  void **e;
120117395Skan  e = htab_find_slot_with_hash (symbol_table, string,
121117395Skan				(*htab_hash_string) (string),
122117395Skan				create ? INSERT : NO_INSERT);
123117395Skan  if (e == NULL)
124117395Skan    return NULL;
125117395Skan  if (*e == NULL)
12650397Sobrien    {
127117395Skan      struct symbol_hash_entry *v;
128169689Skan      *e = v = XCNEW (struct symbol_hash_entry);
129117395Skan      v->key = xstrdup (string);
13050397Sobrien    }
131117395Skan  return *e;
13250397Sobrien}
13350397Sobrien
134117395Skanstatic htab_t file_table;
135117395Skan
13652284Sobrien/* Look up an entry in the file hash table.  */
13752284Sobrien
13850397Sobrienstatic struct file_hash_entry *
139132718Skanfile_hash_lookup (const char *string)
14050397Sobrien{
141132718Skan  void **e;
142117395Skan  e = htab_find_slot_with_hash (file_table, string,
143117395Skan				(*htab_hash_string) (string),
144117395Skan				INSERT);
145117395Skan  if (*e == NULL)
14650397Sobrien    {
147117395Skan      struct file_hash_entry *v;
148169689Skan      *e = v = XCNEW (struct file_hash_entry);
149117395Skan      v->key = xstrdup (string);
15050397Sobrien    }
151117395Skan  return *e;
15250397Sobrien}
15350397Sobrien
154117395Skanstatic htab_t demangled_table;
155117395Skan
15652284Sobrien/* Look up an entry in the demangled name hash table.  */
15752284Sobrien
15850397Sobrienstatic struct demangled_hash_entry *
159132718Skandemangled_hash_lookup (const char *string, int create)
16050397Sobrien{
161132718Skan  void **e;
162117395Skan  e = htab_find_slot_with_hash (demangled_table, string,
163117395Skan				(*htab_hash_string) (string),
164117395Skan				create ? INSERT : NO_INSERT);
165117395Skan  if (e == NULL)
166117395Skan    return NULL;
167117395Skan  if (*e == NULL)
168117395Skan    {
169117395Skan      struct demangled_hash_entry *v;
170169689Skan      *e = v = XCNEW (struct demangled_hash_entry);
171117395Skan      v->key = xstrdup (string);
172117395Skan    }
173117395Skan  return *e;
17450397Sobrien}
17550397Sobrien
17650397Sobrien/* Stack code.  */
17750397Sobrien
17850397Sobrienstruct symbol_stack_entry
17950397Sobrien{
18050397Sobrien  symbol *value;
18150397Sobrien  struct symbol_stack_entry *next;
18250397Sobrien};
18350397Sobrienstruct obstack symbol_stack_obstack;
18450397Sobrienstruct symbol_stack_entry *symbol_stack;
18550397Sobrien
18650397Sobrienstruct file_stack_entry
18750397Sobrien{
18850397Sobrien  file *value;
18950397Sobrien  struct file_stack_entry *next;
19050397Sobrien};
19150397Sobrienstruct obstack file_stack_obstack;
19250397Sobrienstruct file_stack_entry *file_stack;
19350397Sobrien
19450397Sobrienstatic void
195132718Skansymbol_push (symbol *p)
19650397Sobrien{
197132718Skan  struct symbol_stack_entry *ep = obstack_alloc
19850397Sobrien    (&symbol_stack_obstack, sizeof (struct symbol_stack_entry));
19950397Sobrien  ep->value = p;
20050397Sobrien  ep->next = symbol_stack;
20150397Sobrien  symbol_stack = ep;
20250397Sobrien}
20350397Sobrien
20450397Sobrienstatic symbol *
205132718Skansymbol_pop (void)
20650397Sobrien{
20750397Sobrien  struct symbol_stack_entry *ep = symbol_stack;
20850397Sobrien  symbol *p;
20950397Sobrien  if (ep == NULL)
21050397Sobrien    return NULL;
21150397Sobrien  p = ep->value;
21250397Sobrien  symbol_stack = ep->next;
21350397Sobrien  obstack_free (&symbol_stack_obstack, ep);
21450397Sobrien  return p;
21550397Sobrien}
21650397Sobrien
21750397Sobrienstatic void
218132718Skanfile_push (file *p)
21950397Sobrien{
22050397Sobrien  struct file_stack_entry *ep;
22150397Sobrien
22250397Sobrien  if (p->tweaking)
22350397Sobrien    return;
22450397Sobrien
225132718Skan  ep = obstack_alloc
22650397Sobrien    (&file_stack_obstack, sizeof (struct file_stack_entry));
22750397Sobrien  ep->value = p;
22850397Sobrien  ep->next = file_stack;
22950397Sobrien  file_stack = ep;
23050397Sobrien  p->tweaking = 1;
23150397Sobrien}
23250397Sobrien
23350397Sobrienstatic file *
234132718Skanfile_pop (void)
23550397Sobrien{
23650397Sobrien  struct file_stack_entry *ep = file_stack;
23750397Sobrien  file *p;
23850397Sobrien  if (ep == NULL)
23950397Sobrien    return NULL;
24050397Sobrien  p = ep->value;
24150397Sobrien  file_stack = ep->next;
24250397Sobrien  obstack_free (&file_stack_obstack, ep);
24350397Sobrien  p->tweaking = 0;
24450397Sobrien  return p;
24550397Sobrien}
24650397Sobrien
24750397Sobrien/* Other machinery.  */
24850397Sobrien
24952284Sobrien/* Initialize the tlink machinery.  Called from do_tlink.  */
25052284Sobrien
25150397Sobrienstatic void
252132718Skantlink_init (void)
25350397Sobrien{
25490075Sobrien  const char *p;
25550397Sobrien
256117395Skan  symbol_table = htab_create (500, hash_string_hash, hash_string_eq,
257117395Skan			      NULL);
258117395Skan  file_table = htab_create (500, hash_string_hash, hash_string_eq,
259117395Skan			    NULL);
260117395Skan  demangled_table = htab_create (500, hash_string_hash, hash_string_eq,
261117395Skan				 NULL);
262132718Skan
26350397Sobrien  obstack_begin (&symbol_stack_obstack, 0);
26450397Sobrien  obstack_begin (&file_stack_obstack, 0);
26550397Sobrien
26650397Sobrien  p = getenv ("TLINK_VERBOSE");
26750397Sobrien  if (p)
26850397Sobrien    tlink_verbose = atoi (p);
26950397Sobrien  else
27050397Sobrien    {
27150397Sobrien      tlink_verbose = 1;
27250397Sobrien      if (vflag)
27350397Sobrien	tlink_verbose = 2;
27450397Sobrien      if (debug)
27550397Sobrien	tlink_verbose = 3;
27650397Sobrien    }
277169689Skan
278169689Skan  getcwd (initial_cwd, sizeof (initial_cwd));
27950397Sobrien}
28050397Sobrien
28150397Sobrienstatic int
282169689Skantlink_execute (const char *prog, char **argv, const char *outname,
283169689Skan	       const char *errname)
28450397Sobrien{
285169689Skan  struct pex_obj *pex;
286169689Skan
287169689Skan  pex = collect_execute (prog, argv, outname, errname);
288169689Skan  return collect_wait (prog, pex);
289117395Skan}
29050397Sobrien
29150397Sobrienstatic char *
292132718Skanfrob_extension (const char *s, const char *ext)
29350397Sobrien{
29490075Sobrien  const char *p = strrchr (s, '/');
29550397Sobrien  if (! p)
29650397Sobrien    p = s;
29790075Sobrien  p = strrchr (p, '.');
29850397Sobrien  if (! p)
29950397Sobrien    p = s + strlen (s);
30050397Sobrien
30150397Sobrien  obstack_grow (&temporary_obstack, s, p - s);
30250397Sobrien  return obstack_copy0 (&temporary_obstack, ext, strlen (ext));
30350397Sobrien}
30450397Sobrien
30550397Sobrienstatic char *
306132718Skanobstack_fgets (FILE *stream, struct obstack *ob)
30750397Sobrien{
30850397Sobrien  int c;
30950397Sobrien  while ((c = getc (stream)) != EOF && c != '\n')
31050397Sobrien    obstack_1grow (ob, c);
31150397Sobrien  if (obstack_object_size (ob) == 0)
31250397Sobrien    return NULL;
31350397Sobrien  obstack_1grow (ob, '\0');
314169689Skan  return XOBFINISH (ob, char *);
31550397Sobrien}
31650397Sobrien
31750397Sobrienstatic char *
318132718Skantfgets (FILE *stream)
31950397Sobrien{
32050397Sobrien  return obstack_fgets (stream, &temporary_obstack);
32150397Sobrien}
32250397Sobrien
32350397Sobrienstatic char *
324132718Skanpfgets (FILE *stream)
32550397Sobrien{
326117395Skan  return xstrdup (tfgets (stream));
32750397Sobrien}
32850397Sobrien
32950397Sobrien/* Real tlink code.  */
33050397Sobrien
33152284Sobrien/* Subroutine of read_repo_file.  We are reading the repo file for file F,
33252284Sobrien   which is coming in on STREAM, and the symbol that comes next in STREAM
333132718Skan   is offered, chosen or provided if CHOSEN is 0, 1 or 2, respectively.
33452284Sobrien
33552284Sobrien   XXX "provided" is unimplemented, both here and in the compiler.  */
33652284Sobrien
33750397Sobrienstatic void
338132718Skanfreadsym (FILE *stream, file *f, int chosen)
33950397Sobrien{
34050397Sobrien  symbol *sym;
34150397Sobrien
34250397Sobrien  {
34390075Sobrien    const char *name = tfgets (stream);
34450397Sobrien    sym = symbol_hash_lookup (name, true);
34550397Sobrien  }
34650397Sobrien
34750397Sobrien  if (sym->file == NULL)
34850397Sobrien    {
34952284Sobrien      /* We didn't have this symbol already, so we choose this file.  */
35052284Sobrien
35150397Sobrien      symbol_push (sym);
35250397Sobrien      sym->file = f;
35350397Sobrien      sym->chosen = chosen;
35450397Sobrien    }
35550397Sobrien  else if (chosen)
35650397Sobrien    {
35752284Sobrien      /* We want this file; cast aside any pretender.  */
35852284Sobrien
35950397Sobrien      if (sym->chosen && sym->file != f)
36050397Sobrien	{
36150397Sobrien	  if (sym->chosen == 1)
36250397Sobrien	    file_push (sym->file);
36350397Sobrien	  else
36450397Sobrien	    {
36550397Sobrien	      file_push (f);
36650397Sobrien	      f = sym->file;
36750397Sobrien	      chosen = sym->chosen;
36850397Sobrien	    }
36950397Sobrien	}
37050397Sobrien      sym->file = f;
37150397Sobrien      sym->chosen = chosen;
37250397Sobrien    }
37350397Sobrien}
37450397Sobrien
37552284Sobrien/* Read in the repo file denoted by F, and record all its information.  */
37652284Sobrien
37750397Sobrienstatic void
378132718Skanread_repo_file (file *f)
37950397Sobrien{
38050397Sobrien  char c;
381117395Skan  FILE *stream = fopen (f->key, "r");
38250397Sobrien
38350397Sobrien  if (tlink_verbose >= 2)
384260012Spfg    fprintf (stderr, "%s", _("collect: reading %s\n"), f->key);
38550397Sobrien
38650397Sobrien  while (fscanf (stream, "%c ", &c) == 1)
38750397Sobrien    {
38850397Sobrien      switch (c)
38950397Sobrien	{
39050397Sobrien	case 'A':
39150397Sobrien	  f->args = pfgets (stream);
39250397Sobrien	  break;
39350397Sobrien	case 'D':
39450397Sobrien	  f->dir = pfgets (stream);
39550397Sobrien	  break;
39650397Sobrien	case 'M':
39750397Sobrien	  f->main = pfgets (stream);
39850397Sobrien	  break;
39950397Sobrien	case 'P':
40050397Sobrien	  freadsym (stream, f, 2);
40150397Sobrien	  break;
40250397Sobrien	case 'C':
40350397Sobrien	  freadsym (stream, f, 1);
40450397Sobrien	  break;
40550397Sobrien	case 'O':
40650397Sobrien	  freadsym (stream, f, 0);
40750397Sobrien	  break;
40850397Sobrien	}
40950397Sobrien      obstack_free (&temporary_obstack, temporary_firstobj);
41050397Sobrien    }
41150397Sobrien  fclose (stream);
41250397Sobrien  if (f->args == NULL)
41350397Sobrien    f->args = getenv ("COLLECT_GCC_OPTIONS");
41450397Sobrien  if (f->dir == NULL)
41550397Sobrien    f->dir = ".";
41650397Sobrien}
41750397Sobrien
41852284Sobrien/* We might want to modify LINE, which is a symbol line from file F.  We do
41952284Sobrien   this if either we saw an error message referring to the symbol in
42052284Sobrien   question, or we have already allocated the symbol to another file and
42152284Sobrien   this one wants to emit it as well.  */
42252284Sobrien
42350397Sobrienstatic void
424132718Skanmaybe_tweak (char *line, file *f)
42550397Sobrien{
42650397Sobrien  symbol *sym = symbol_hash_lookup (line + 2, false);
42750397Sobrien
42850397Sobrien  if ((sym->file == f && sym->tweaking)
42950397Sobrien      || (sym->file != f && line[0] == 'C'))
43050397Sobrien    {
43150397Sobrien      sym->tweaking = 0;
43250397Sobrien      sym->tweaked = 1;
43350397Sobrien
43450397Sobrien      if (line[0] == 'O')
43550397Sobrien	line[0] = 'C';
43650397Sobrien      else
43750397Sobrien	line[0] = 'O';
43850397Sobrien    }
43950397Sobrien}
44050397Sobrien
44152284Sobrien/* Update the repo files for each of the object files we have adjusted and
442169689Skan   recompile.  */
44352284Sobrien
44450397Sobrienstatic int
445132718Skanrecompile_files (void)
44650397Sobrien{
44750397Sobrien  file *f;
44850397Sobrien
449122180Skan  putenv (xstrdup ("COMPILER_PATH="));
450122180Skan  putenv (xstrdup ("LIBRARY_PATH="));
451117395Skan
45250397Sobrien  while ((f = file_pop ()) != NULL)
45350397Sobrien    {
454169689Skan      char *line;
455169689Skan      const char *p, *q;
456169689Skan      char **argv;
457169689Skan      struct obstack arg_stack;
458117395Skan      FILE *stream = fopen (f->key, "r");
459117395Skan      const char *const outname = frob_extension (f->key, ".rnw");
46050397Sobrien      FILE *output = fopen (outname, "w");
46150397Sobrien
46250397Sobrien      while ((line = tfgets (stream)) != NULL)
46350397Sobrien	{
46450397Sobrien	  switch (line[0])
46550397Sobrien	    {
46650397Sobrien	    case 'C':
46750397Sobrien	    case 'O':
46850397Sobrien	      maybe_tweak (line, f);
46950397Sobrien	    }
47050397Sobrien	  fprintf (output, "%s\n", line);
47150397Sobrien	}
47250397Sobrien      fclose (stream);
47350397Sobrien      fclose (output);
474169689Skan      /* On Windows "rename" returns -1 and sets ERRNO to EACCESS if
475169689Skan	 the new file name already exists.  Therefore, we explicitly
476169689Skan	 remove the old file first.  */
477169689Skan      if (remove (f->key) == -1)
478169689Skan	fatal_perror ("removing .rpo file");
479169689Skan      if (rename (outname, f->key) == -1)
480169689Skan	fatal_perror ("renaming .rpo file");
48150397Sobrien
482169689Skan      if (!f->args)
483169689Skan	{
484169689Skan	  error ("repository file '%s' does not contain command-line "
485169689Skan		 "arguments", f->key);
486169689Skan	  return 0;
487169689Skan	}
48850397Sobrien
489169689Skan      /* Build a null-terminated argv array suitable for
490169689Skan	 tlink_execute().  Manipulate arguments on the arg_stack while
491169689Skan	 building argv on the temporary_obstack.  */
492169689Skan
493169689Skan      obstack_init (&arg_stack);
494169689Skan      obstack_ptr_grow (&temporary_obstack, c_file_name);
495169689Skan
496169689Skan      for (p = f->args; *p != '\0'; p = q + 1)
497169689Skan	{
498169689Skan	  /* Arguments are delimited by single-quotes.  Find the
499169689Skan	     opening quote.  */
500169689Skan	  p = strchr (p, '\'');
501169689Skan	  if (!p)
502169689Skan	    goto done;
503169689Skan
504169689Skan	  /* Find the closing quote.  */
505169689Skan	  q = strchr (p + 1, '\'');
506169689Skan	  if (!q)
507169689Skan	    goto done;
508169689Skan
509169689Skan	  obstack_grow (&arg_stack, p + 1, q - (p + 1));
510169689Skan
511169689Skan	  /* Replace '\'' with '.  This is how set_collect_gcc_options
512169689Skan	     encodes a single-quote.  */
513169689Skan	  while (q[1] == '\\' && q[2] == '\'' && q[3] == '\'')
514169689Skan	    {
515169689Skan	      const char *r;
516169689Skan
517169689Skan	      r = strchr (q + 4, '\'');
518169689Skan	      if (!r)
519169689Skan		goto done;
520169689Skan
521169689Skan	      obstack_grow (&arg_stack, q + 3, r - (q + 3));
522169689Skan	      q = r;
523169689Skan	    }
524169689Skan
525169689Skan	  obstack_1grow (&arg_stack, '\0');
526169689Skan	  obstack_ptr_grow (&temporary_obstack, obstack_finish (&arg_stack));
527169689Skan	}
528169689Skan    done:
529169689Skan      obstack_ptr_grow (&temporary_obstack, f->main);
530169689Skan      obstack_ptr_grow (&temporary_obstack, NULL);
531169689Skan      argv = XOBFINISH (&temporary_obstack, char **);
532169689Skan
53350397Sobrien      if (tlink_verbose)
53490075Sobrien	fprintf (stderr, _("collect: recompiling %s\n"), f->main);
53550397Sobrien
536169689Skan      if (chdir (f->dir) != 0
537169689Skan	  || tlink_execute (c_file_name, argv, NULL, NULL) != 0
538169689Skan	  || chdir (initial_cwd) != 0)
53950397Sobrien	return 0;
54050397Sobrien
54150397Sobrien      read_repo_file (f);
54250397Sobrien
543169689Skan      obstack_free (&arg_stack, NULL);
54450397Sobrien      obstack_free (&temporary_obstack, temporary_firstobj);
54550397Sobrien    }
54650397Sobrien  return 1;
54750397Sobrien}
54850397Sobrien
54952284Sobrien/* The first phase of processing: determine which object files have
55052284Sobrien   .rpo files associated with them, and read in the information.  */
55152284Sobrien
55250397Sobrienstatic int
553132718Skanread_repo_files (char **object_lst)
55450397Sobrien{
55550397Sobrien  char **object = object_lst;
55650397Sobrien
55750397Sobrien  for (; *object; object++)
55850397Sobrien    {
55990075Sobrien      const char *p;
56050397Sobrien      file *f;
56150397Sobrien
56290075Sobrien      /* Don't bother trying for ld flags.  */
56390075Sobrien      if (*object[0] == '-')
56490075Sobrien	continue;
56590075Sobrien
56690075Sobrien      p = frob_extension (*object, ".rpo");
56790075Sobrien
56850397Sobrien      if (! file_exists (p))
56950397Sobrien	continue;
57050397Sobrien
57150397Sobrien      f = file_hash_lookup (p);
57250397Sobrien
57350397Sobrien      read_repo_file (f);
57450397Sobrien    }
57550397Sobrien
57650397Sobrien  if (file_stack != NULL && ! recompile_files ())
57750397Sobrien    return 0;
57850397Sobrien
57950397Sobrien  return (symbol_stack != NULL);
58050397Sobrien}
58150397Sobrien
58252284Sobrien/* Add the demangled forms of any new symbols to the hash table.  */
58352284Sobrien
58450397Sobrienstatic void
585132718Skandemangle_new_symbols (void)
58650397Sobrien{
58750397Sobrien  symbol *sym;
58850397Sobrien
58950397Sobrien  while ((sym = symbol_pop ()) != NULL)
59050397Sobrien    {
59150397Sobrien      demangled *dem;
592117395Skan      const char *p = cplus_demangle (sym->key, DMGL_PARAMS | DMGL_ANSI);
59350397Sobrien
59450397Sobrien      if (! p)
59550397Sobrien	continue;
59650397Sobrien
59750397Sobrien      dem = demangled_hash_lookup (p, true);
598117395Skan      dem->mangled = sym->key;
59950397Sobrien    }
60050397Sobrien}
60150397Sobrien
60252284Sobrien/* Step through the output of the linker, in the file named FNAME, and
60352284Sobrien   adjust the settings for each symbol encountered.  */
60452284Sobrien
60550397Sobrienstatic int
606132718Skanscan_linker_output (const char *fname)
60750397Sobrien{
60850397Sobrien  FILE *stream = fopen (fname, "r");
60950397Sobrien  char *line;
610169689Skan  int skip_next_in_line = 0;
61150397Sobrien
61250397Sobrien  while ((line = tfgets (stream)) != NULL)
61350397Sobrien    {
61450397Sobrien      char *p = line, *q;
61550397Sobrien      symbol *sym;
61650397Sobrien      int end;
617169689Skan      int ok = 0;
618117395Skan
619169689Skan      /* On darwin9, we might have to skip " in " lines as well.  */
620169689Skan      if (skip_next_in_line
621169689Skan	  && strstr (p, " in "))
622169689Skan	  continue;
623169689Skan      skip_next_in_line = 0;
624169689Skan
625117395Skan      while (*p && ISSPACE ((unsigned char) *p))
62650397Sobrien	++p;
62750397Sobrien
62850397Sobrien      if (! *p)
62950397Sobrien	continue;
63050397Sobrien
631117395Skan      for (q = p; *q && ! ISSPACE ((unsigned char) *q); ++q)
63250397Sobrien	;
63350397Sobrien
63450397Sobrien      /* Try the first word on the line.  */
63550397Sobrien      if (*p == '.')
63650397Sobrien	++p;
637117395Skan      if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)))
638117395Skan	p += strlen (USER_LABEL_PREFIX);
63950397Sobrien
64050397Sobrien      end = ! *q;
64150397Sobrien      *q = 0;
64250397Sobrien      sym = symbol_hash_lookup (p, false);
64350397Sobrien
64490075Sobrien      /* Some SVR4 linkers produce messages like
64590075Sobrien	 ld: 0711-317 ERROR: Undefined symbol: .g__t3foo1Zi
64690075Sobrien	 */
647117395Skan      if (! sym && ! end && strstr (q + 1, "Undefined symbol: "))
64890075Sobrien	{
649117395Skan	  char *p = strrchr (q + 1, ' ');
65090075Sobrien	  p++;
65190075Sobrien	  if (*p == '.')
65290075Sobrien	    p++;
653117395Skan	  if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)))
654117395Skan	    p += strlen (USER_LABEL_PREFIX);
65590075Sobrien	  sym = symbol_hash_lookup (p, false);
65690075Sobrien	}
65790075Sobrien
65850397Sobrien      if (! sym && ! end)
65952284Sobrien	/* Try a mangled name in quotes.  */
66050397Sobrien	{
661117395Skan	  const char *oldq = q + 1;
66250397Sobrien	  demangled *dem = 0;
66350397Sobrien	  q = 0;
66450397Sobrien
665169689Skan	  /* On darwin9, we look for "foo" referenced from:\n\(.* in .*\n\)*  */
666169689Skan	  if (strcmp (oldq, "referenced from:") == 0)
667169689Skan	    {
668169689Skan	      /* We have to remember that we found a symbol to tweak.  */
669169689Skan	      ok = 1;
670169689Skan
671169689Skan	      /* We actually want to start from the first word on the
672169689Skan		 line.  */
673169689Skan	      oldq = p;
674169689Skan
675169689Skan	      /* Since the format is multiline, we have to skip
676169689Skan		 following lines with " in ".  */
677169689Skan	      skip_next_in_line = 1;
678169689Skan	    }
679169689Skan
68052284Sobrien	  /* First try `GNU style'.  */
68190075Sobrien	  p = strchr (oldq, '`');
68252284Sobrien	  if (p)
68390075Sobrien	    p++, q = strchr (p, '\'');
68452284Sobrien	  /* Then try "double quotes".  */
68590075Sobrien	  else if (p = strchr (oldq, '"'), p)
68690075Sobrien	    p++, q = strchr (p, '"');
687132718Skan	  else {
688132718Skan	    /* Then try entire line.  */
689132718Skan	    q = strchr (oldq, 0);
690132718Skan	    if (q != oldq)
691132718Skan	      p = (char *)oldq;
692132718Skan	  }
69350397Sobrien
69490075Sobrien	  if (p)
695117395Skan	    {
696117395Skan	      /* Don't let the strstr's below see the demangled name; we
697117395Skan		 might get spurious matches.  */
698117395Skan	      p[-1] = '\0';
69990075Sobrien
700117395Skan	      /* powerpc64-linux references .foo when calling function foo.  */
701117395Skan	      if (*p == '.')
702117395Skan		p++;
703117395Skan	    }
704117395Skan
70590075Sobrien	  /* We need to check for certain error keywords here, or we would
70690075Sobrien	     mistakenly use GNU ld's "In function `foo':" message.  */
707169689Skan	  if (q && (ok
708169689Skan		    || strstr (oldq, "ndefined")
70990075Sobrien		    || strstr (oldq, "nresolved")
71090075Sobrien		    || strstr (oldq, "nsatisfied")
71190075Sobrien		    || strstr (oldq, "ultiple")))
71250397Sobrien	    {
71352284Sobrien	      *q = 0;
71452284Sobrien	      dem = demangled_hash_lookup (p, false);
71552284Sobrien	      if (dem)
71652284Sobrien		sym = symbol_hash_lookup (dem->mangled, false);
71752284Sobrien	      else
718117395Skan		{
719117395Skan		  if (!strncmp (p, USER_LABEL_PREFIX,
720117395Skan				strlen (USER_LABEL_PREFIX)))
721117395Skan		    p += strlen (USER_LABEL_PREFIX);
72252750Sobrien		  sym = symbol_hash_lookup (p, false);
72352750Sobrien		}
72450397Sobrien	    }
72550397Sobrien	}
72650397Sobrien
72750397Sobrien      if (sym && sym->tweaked)
72850397Sobrien	{
729169689Skan	  error ("'%s' was assigned to '%s', but was not defined "
730169689Skan		 "during recompilation, or vice versa",
731169689Skan		 sym->key, sym->file->key);
73250397Sobrien	  fclose (stream);
73350397Sobrien	  return 0;
73450397Sobrien	}
73550397Sobrien      if (sym && !sym->tweaking)
73650397Sobrien	{
73750397Sobrien	  if (tlink_verbose >= 2)
73890075Sobrien	    fprintf (stderr, _("collect: tweaking %s in %s\n"),
739117395Skan		     sym->key, sym->file->key);
74050397Sobrien	  sym->tweaking = 1;
74150397Sobrien	  file_push (sym->file);
74250397Sobrien	}
743117395Skan
74450397Sobrien      obstack_free (&temporary_obstack, temporary_firstobj);
74550397Sobrien    }
74650397Sobrien
74750397Sobrien  fclose (stream);
74850397Sobrien  return (file_stack != NULL);
74950397Sobrien}
75050397Sobrien
75152284Sobrien/* Entry point for tlink.  Called from main in collect2.c.
75252284Sobrien
75352284Sobrien   Iteratively try to provide definitions for all the unresolved symbols
75452284Sobrien   mentioned in the linker error messages.
75552284Sobrien
75652284Sobrien   LD_ARGV is an array of arguments for the linker.
75752284Sobrien   OBJECT_LST is an array of object files that we may be able to recompile
75852284Sobrien     to provide missing definitions.  Currently ignored.  */
75952284Sobrien
76050397Sobrienvoid
761132718Skando_tlink (char **ld_argv, char **object_lst ATTRIBUTE_UNUSED)
76250397Sobrien{
763169689Skan  int exit = tlink_execute ("ld", ld_argv, ldout, lderrout);
76450397Sobrien
76550397Sobrien  tlink_init ();
76650397Sobrien
76750397Sobrien  if (exit)
76850397Sobrien    {
76950397Sobrien      int i = 0;
77050397Sobrien
77150397Sobrien      /* Until collect does a better job of figuring out which are object
77250397Sobrien	 files, assume that everything on the command line could be.  */
77350397Sobrien      if (read_repo_files (ld_argv))
77450397Sobrien	while (exit && i++ < MAX_ITERATIONS)
77550397Sobrien	  {
77650397Sobrien	    if (tlink_verbose >= 3)
777169689Skan	      {
778169689Skan		dump_file (ldout, stdout);
779169689Skan		dump_file (lderrout, stderr);
780169689Skan	      }
78150397Sobrien	    demangle_new_symbols ();
782169689Skan	    if (! scan_linker_output (ldout)
783169689Skan		&& ! scan_linker_output (lderrout))
78450397Sobrien	      break;
78550397Sobrien	    if (! recompile_files ())
78650397Sobrien	      break;
78750397Sobrien	    if (tlink_verbose)
78890075Sobrien	      fprintf (stderr, _("collect: relinking\n"));
789169689Skan	    exit = tlink_execute ("ld", ld_argv, ldout, lderrout);
79050397Sobrien	  }
79150397Sobrien    }
79250397Sobrien
793169689Skan  dump_file (ldout, stdout);
79450397Sobrien  unlink (ldout);
795169689Skan  dump_file (lderrout, stderr);
796169689Skan  unlink (lderrout);
79750397Sobrien  if (exit)
79850397Sobrien    {
79950397Sobrien      error ("ld returned %d exit status", exit);
80050397Sobrien      collect_exit (exit);
80150397Sobrien    }
80250397Sobrien}
803