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