X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Ftlink.c;h=7b589832b06ce799fde99fec725666e764e36e22;hp=ea1ce3a4db10ce6eea8031da192df573eda51be2;hb=2f1ce05cf95e354ae01c6801d32fb518f97fa593;hpb=805e22b2051e9c6a75377ea6599654d7415da483 diff --git a/gcc/tlink.c b/gcc/tlink.c index ea1ce3a4db1..7b589832b06 100644 --- a/gcc/tlink.c +++ b/gcc/tlink.c @@ -1,14 +1,15 @@ /* Scan linker error messages for missing template instantiations and provide them. - Copyright (C) 1995, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 1995, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2007, 2008 + Free Software Foundation, Inc. Contributed by Jason Merrill (jason@cygnus.com). This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later +Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY @@ -17,9 +18,8 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ +along with GCC; see the file COPYING3. If not see +. */ #include "config.h" #include "system.h" @@ -30,6 +30,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "hashtab.h" #include "demangle.h" #include "collect2.h" +#include "libiberty.h" + +/* TARGET_64BIT may be defined to use driver specific functionality. */ +#undef TARGET_64BIT +#define TARGET_64BIT TARGET_64BIT_DEFAULT #define MAX_ITERATIONS 17 @@ -37,6 +42,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA extern int prepends_underscore; static int tlink_verbose; + +static char *initial_cwd; /* Hash table boilerplate for working with htab_t. We have hash tables for symbol names, file names, and demangled symbols. */ @@ -67,13 +74,11 @@ typedef struct demangled_hash_entry /* Hash and comparison functions for these hash tables. */ -static int hash_string_eq PARAMS ((const void *, const void *)); -static hashval_t hash_string_hash PARAMS ((const void *)); +static int hash_string_eq (const void *, const void *); +static hashval_t hash_string_hash (const void *); static int -hash_string_eq (s1_p, s2_p) - const void *s1_p; - const void *s2_p; +hash_string_eq (const void *s1_p, const void *s2_p) { const char *const *s1 = (const char *const *) s1_p; const char *s2 = (const char *) s2_p; @@ -81,8 +86,7 @@ hash_string_eq (s1_p, s2_p) } static hashval_t -hash_string_hash (s_p) - const void *s_p; +hash_string_hash (const void *s_p) { const char *const *s = (const char *const *) s_p; return (*htab_hash_string) (*s); @@ -90,37 +94,33 @@ hash_string_hash (s_p) static htab_t symbol_table; -static struct symbol_hash_entry * symbol_hash_lookup PARAMS ((const char *, - int)); -static struct file_hash_entry * file_hash_lookup PARAMS ((const char *)); -static struct demangled_hash_entry * - demangled_hash_lookup PARAMS ((const char *, int)); -static void symbol_push PARAMS ((symbol *)); -static symbol * symbol_pop PARAMS ((void)); -static void file_push PARAMS ((file *)); -static file * file_pop PARAMS ((void)); -static void tlink_init PARAMS ((void)); -static int tlink_execute PARAMS ((const char *, char **, const char *)); -static char * frob_extension PARAMS ((const char *, const char *)); -static char * obstack_fgets PARAMS ((FILE *, struct obstack *)); -static char * tfgets PARAMS ((FILE *)); -static char * pfgets PARAMS ((FILE *)); -static void freadsym PARAMS ((FILE *, file *, int)); -static void read_repo_file PARAMS ((file *)); -static void maybe_tweak PARAMS ((char *, file *)); -static int recompile_files PARAMS ((void)); -static int read_repo_files PARAMS ((char **)); -static void demangle_new_symbols PARAMS ((void)); -static int scan_linker_output PARAMS ((const char *)); +static struct symbol_hash_entry * symbol_hash_lookup (const char *, int); +static struct file_hash_entry * file_hash_lookup (const char *); +static struct demangled_hash_entry *demangled_hash_lookup (const char *, int); +static void symbol_push (symbol *); +static symbol * symbol_pop (void); +static void file_push (file *); +static file * file_pop (void); +static void tlink_init (void); +static int tlink_execute (const char *, char **, const char *, const char *); +static char * frob_extension (const char *, const char *); +static char * obstack_fgets (FILE *, struct obstack *); +static char * tfgets (FILE *); +static char * pfgets (FILE *); +static void freadsym (FILE *, file *, int); +static void read_repo_file (file *); +static void maybe_tweak (char *, file *); +static int recompile_files (void); +static int read_repo_files (char **); +static void demangle_new_symbols (void); +static int scan_linker_output (const char *); /* Look up an entry in the symbol hash table. */ static struct symbol_hash_entry * -symbol_hash_lookup (string, create) - const char *string; - int create; +symbol_hash_lookup (const char *string, int create) { - PTR *e; + void **e; e = htab_find_slot_with_hash (symbol_table, string, (*htab_hash_string) (string), create ? INSERT : NO_INSERT); @@ -129,10 +129,10 @@ symbol_hash_lookup (string, create) if (*e == NULL) { struct symbol_hash_entry *v; - *e = v = xcalloc (1, sizeof (*v)); + *e = v = XCNEW (struct symbol_hash_entry); v->key = xstrdup (string); } - return *e; + return (struct symbol_hash_entry *) *e; } static htab_t file_table; @@ -140,20 +140,19 @@ static htab_t file_table; /* Look up an entry in the file hash table. */ static struct file_hash_entry * -file_hash_lookup (string) - const char *string; +file_hash_lookup (const char *string) { - PTR *e; + void **e; e = htab_find_slot_with_hash (file_table, string, (*htab_hash_string) (string), INSERT); if (*e == NULL) { struct file_hash_entry *v; - *e = v = xcalloc (1, sizeof (*v)); + *e = v = XCNEW (struct file_hash_entry); v->key = xstrdup (string); } - return *e; + return (struct file_hash_entry *) *e; } static htab_t demangled_table; @@ -161,11 +160,9 @@ static htab_t demangled_table; /* Look up an entry in the demangled name hash table. */ static struct demangled_hash_entry * -demangled_hash_lookup (string, create) - const char *string; - int create; +demangled_hash_lookup (const char *string, int create) { - PTR *e; + void **e; e = htab_find_slot_with_hash (demangled_table, string, (*htab_hash_string) (string), create ? INSERT : NO_INSERT); @@ -174,10 +171,10 @@ demangled_hash_lookup (string, create) if (*e == NULL) { struct demangled_hash_entry *v; - *e = v = xcalloc (1, sizeof (*v)); + *e = v = XCNEW (struct demangled_hash_entry); v->key = xstrdup (string); } - return *e; + return (struct demangled_hash_entry *) *e; } /* Stack code. */ @@ -199,18 +196,17 @@ struct obstack file_stack_obstack; struct file_stack_entry *file_stack; static void -symbol_push (p) - symbol *p; +symbol_push (symbol *p) { - struct symbol_stack_entry *ep = (struct symbol_stack_entry *) obstack_alloc - (&symbol_stack_obstack, sizeof (struct symbol_stack_entry)); + struct symbol_stack_entry *ep + = XOBNEW (&symbol_stack_obstack, struct symbol_stack_entry); ep->value = p; ep->next = symbol_stack; symbol_stack = ep; } static symbol * -symbol_pop () +symbol_pop (void) { struct symbol_stack_entry *ep = symbol_stack; symbol *p; @@ -223,16 +219,14 @@ symbol_pop () } static void -file_push (p) - file *p; +file_push (file *p) { struct file_stack_entry *ep; if (p->tweaking) return; - ep = (struct file_stack_entry *) obstack_alloc - (&file_stack_obstack, sizeof (struct file_stack_entry)); + ep = XOBNEW (&file_stack_obstack, struct file_stack_entry); ep->value = p; ep->next = file_stack; file_stack = ep; @@ -240,7 +234,7 @@ file_push (p) } static file * -file_pop () +file_pop (void) { struct file_stack_entry *ep = file_stack; file *p; @@ -258,7 +252,7 @@ file_pop () /* Initialize the tlink machinery. Called from do_tlink. */ static void -tlink_init () +tlink_init (void) { const char *p; @@ -268,7 +262,7 @@ tlink_init () NULL); demangled_table = htab_create (500, hash_string_hash, hash_string_eq, NULL); - + obstack_begin (&symbol_stack_obstack, 0); obstack_begin (&file_stack_obstack, 0); @@ -283,22 +277,22 @@ tlink_init () if (debug) tlink_verbose = 3; } + + initial_cwd = getpwd (); } static int -tlink_execute (prog, argv, redir) - const char *prog; - char **argv; - const char *redir; +tlink_execute (const char *prog, char **argv, const char *outname, + const char *errname) { - collect_execute (prog, argv, redir); - return collect_wait (prog); + struct pex_obj *pex; + + pex = collect_execute (prog, argv, outname, errname, PEX_LAST | PEX_SEARCH); + return collect_wait (prog, pex); } static char * -frob_extension (s, ext) - const char *s; - const char *ext; +frob_extension (const char *s, const char *ext) { const char *p = strrchr (s, '/'); if (! p) @@ -308,13 +302,11 @@ frob_extension (s, ext) p = s + strlen (s); obstack_grow (&temporary_obstack, s, p - s); - return obstack_copy0 (&temporary_obstack, ext, strlen (ext)); + return (char *) obstack_copy0 (&temporary_obstack, ext, strlen (ext)); } static char * -obstack_fgets (stream, ob) - FILE *stream; - struct obstack *ob; +obstack_fgets (FILE *stream, struct obstack *ob) { int c; while ((c = getc (stream)) != EOF && c != '\n') @@ -322,19 +314,17 @@ obstack_fgets (stream, ob) if (obstack_object_size (ob) == 0) return NULL; obstack_1grow (ob, '\0'); - return obstack_finish (ob); + return XOBFINISH (ob, char *); } static char * -tfgets (stream) - FILE *stream; +tfgets (FILE *stream) { return obstack_fgets (stream, &temporary_obstack); } static char * -pfgets (stream) - FILE *stream; +pfgets (FILE *stream) { return xstrdup (tfgets (stream)); } @@ -343,15 +333,12 @@ pfgets (stream) /* Subroutine of read_repo_file. We are reading the repo file for file F, which is coming in on STREAM, and the symbol that comes next in STREAM - is offerred, chosen or provided if CHOSEN is 0, 1 or 2, respectively. + is offered, chosen or provided if CHOSEN is 0, 1 or 2, respectively. XXX "provided" is unimplemented, both here and in the compiler. */ static void -freadsym (stream, f, chosen) - FILE *stream; - file *f; - int chosen; +freadsym (FILE *stream, file *f, int chosen) { symbol *sym; @@ -391,8 +378,7 @@ freadsym (stream, f, chosen) /* Read in the repo file denoted by F, and record all its information. */ static void -read_repo_file (f) - file *f; +read_repo_file (file *f) { char c; FILE *stream = fopen (f->key, "r"); @@ -438,9 +424,7 @@ read_repo_file (f) this one wants to emit it as well. */ static void -maybe_tweak (line, f) - char *line; - file *f; +maybe_tweak (char *line, file *f) { symbol *sym = symbol_hash_lookup (line + 2, false); @@ -458,21 +442,22 @@ maybe_tweak (line, f) } /* Update the repo files for each of the object files we have adjusted and - recompile. - - XXX Should this use collect_execute instead of system? */ + recompile. */ static int -recompile_files () +recompile_files (void) { file *f; - putenv (xstrdup ("COMPILER_PATH")); - putenv (xstrdup ("LIBRARY_PATH")); + putenv (xstrdup ("COMPILER_PATH=")); + putenv (xstrdup ("LIBRARY_PATH=")); while ((f = file_pop ()) != NULL) { - char *line, *command; + char *line; + const char *p, *q; + char **argv; + struct obstack arg_stack; FILE *stream = fopen (f->key, "r"); const char *const outname = frob_extension (f->key, ".rnw"); FILE *output = fopen (outname, "w"); @@ -489,27 +474,76 @@ recompile_files () } fclose (stream); fclose (output); - rename (outname, f->key); + /* On Windows "rename" returns -1 and sets ERRNO to EACCESS if + the new file name already exists. Therefore, we explicitly + remove the old file first. */ + if (remove (f->key) == -1) + fatal_perror ("removing .rpo file"); + if (rename (outname, f->key) == -1) + fatal_perror ("renaming .rpo file"); + + if (!f->args) + { + error ("repository file '%s' does not contain command-line " + "arguments", f->key); + return 0; + } + + /* Build a null-terminated argv array suitable for + tlink_execute(). Manipulate arguments on the arg_stack while + building argv on the temporary_obstack. */ + + obstack_init (&arg_stack); + obstack_ptr_grow (&temporary_obstack, c_file_name); + + for (p = f->args; *p != '\0'; p = q + 1) + { + /* Arguments are delimited by single-quotes. Find the + opening quote. */ + p = strchr (p, '\''); + if (!p) + goto done; + + /* Find the closing quote. */ + q = strchr (p + 1, '\''); + if (!q) + goto done; + + obstack_grow (&arg_stack, p + 1, q - (p + 1)); + + /* Replace '\'' with '. This is how set_collect_gcc_options + encodes a single-quote. */ + while (q[1] == '\\' && q[2] == '\'' && q[3] == '\'') + { + const char *r; - obstack_grow (&temporary_obstack, "cd ", 3); - obstack_grow (&temporary_obstack, f->dir, strlen (f->dir)); - obstack_grow (&temporary_obstack, "; ", 2); - obstack_grow (&temporary_obstack, c_file_name, strlen (c_file_name)); - obstack_1grow (&temporary_obstack, ' '); - obstack_grow (&temporary_obstack, f->args, strlen (f->args)); - obstack_1grow (&temporary_obstack, ' '); - command = obstack_copy0 (&temporary_obstack, f->main, strlen (f->main)); + r = strchr (q + 4, '\''); + if (!r) + goto done; + + obstack_grow (&arg_stack, q + 3, r - (q + 3)); + q = r; + } + + obstack_1grow (&arg_stack, '\0'); + obstack_ptr_grow (&temporary_obstack, obstack_finish (&arg_stack)); + } + done: + obstack_ptr_grow (&temporary_obstack, f->main); + obstack_ptr_grow (&temporary_obstack, NULL); + argv = XOBFINISH (&temporary_obstack, char **); if (tlink_verbose) fprintf (stderr, _("collect: recompiling %s\n"), f->main); - if (tlink_verbose >= 3) - fprintf (stderr, "%s\n", command); - if (system (command) != 0) + if (chdir (f->dir) != 0 + || tlink_execute (c_file_name, argv, NULL, NULL) != 0 + || chdir (initial_cwd) != 0) return 0; read_repo_file (f); + obstack_free (&arg_stack, NULL); obstack_free (&temporary_obstack, temporary_firstobj); } return 1; @@ -519,8 +553,7 @@ recompile_files () .rpo files associated with them, and read in the information. */ static int -read_repo_files (object_lst) - char **object_lst; +read_repo_files (char **object_lst) { char **object = object_lst; @@ -552,7 +585,7 @@ read_repo_files (object_lst) /* Add the demangled forms of any new symbols to the hash table. */ static void -demangle_new_symbols () +demangle_new_symbols (void) { symbol *sym; @@ -573,17 +606,24 @@ demangle_new_symbols () adjust the settings for each symbol encountered. */ static int -scan_linker_output (fname) - const char *fname; +scan_linker_output (const char *fname) { FILE *stream = fopen (fname, "r"); char *line; + int skip_next_in_line = 0; while ((line = tfgets (stream)) != NULL) { char *p = line, *q; symbol *sym; int end; + int ok = 0; + + /* On darwin9, we might have to skip " in " lines as well. */ + if (skip_next_in_line + && strstr (p, " in ")) + continue; + skip_next_in_line = 0; while (*p && ISSPACE ((unsigned char) *p)) ++p; @@ -621,10 +661,25 @@ scan_linker_output (fname) if (! sym && ! end) /* Try a mangled name in quotes. */ { - const char *oldq = q + 1; + char *oldq = q + 1; demangled *dem = 0; q = 0; + /* On darwin9, we look for "foo" referenced from:\n\(.* in .*\n\)* */ + if (strcmp (oldq, "referenced from:") == 0) + { + /* We have to remember that we found a symbol to tweak. */ + ok = 1; + + /* We actually want to start from the first word on the + line. */ + oldq = p; + + /* Since the format is multiline, we have to skip + following lines with " in ". */ + skip_next_in_line = 1; + } + /* First try `GNU style'. */ p = strchr (oldq, '`'); if (p) @@ -632,15 +687,31 @@ scan_linker_output (fname) /* Then try "double quotes". */ else if (p = strchr (oldq, '"'), p) p++, q = strchr (p, '"'); + /* Then try 'single quotes'. */ + else if (p = strchr (oldq, '\''), p) + p++, q = strchr (p, '\''); + else { + /* Then try entire line. */ + q = strchr (oldq, 0); + if (q != oldq) + p = (char *)oldq; + } - /* Don't let the strstr's below see the demangled name; we - might get spurious matches. */ if (p) - p[-1] = '\0'; + { + /* Don't let the strstr's below see the demangled name; we + might get spurious matches. */ + p[-1] = '\0'; + + /* powerpc64-linux references .foo when calling function foo. */ + if (*p == '.') + p++; + } /* We need to check for certain error keywords here, or we would mistakenly use GNU ld's "In function `foo':" message. */ - if (q && (strstr (oldq, "ndefined") + if (q && (ok + || strstr (oldq, "ndefined") || strstr (oldq, "nresolved") || strstr (oldq, "nsatisfied") || strstr (oldq, "ultiple"))) @@ -661,6 +732,9 @@ scan_linker_output (fname) if (sym && sym->tweaked) { + error ("'%s' was assigned to '%s', but was not defined " + "during recompilation, or vice versa", + sym->key, sym->file->key); fclose (stream); return 0; } @@ -690,10 +764,9 @@ scan_linker_output (fname) to provide missing definitions. Currently ignored. */ void -do_tlink (ld_argv, object_lst) - char **ld_argv, **object_lst ATTRIBUTE_UNUSED; +do_tlink (char **ld_argv, char **object_lst ATTRIBUTE_UNUSED) { - int exit = tlink_execute ("ld", ld_argv, ldout); + int exit = tlink_execute ("ld", ld_argv, ldout, lderrout); tlink_init (); @@ -707,20 +780,26 @@ do_tlink (ld_argv, object_lst) while (exit && i++ < MAX_ITERATIONS) { if (tlink_verbose >= 3) - dump_file (ldout); + { + dump_file (ldout, stdout); + dump_file (lderrout, stderr); + } demangle_new_symbols (); - if (! scan_linker_output (ldout)) + if (! scan_linker_output (ldout) + && ! scan_linker_output (lderrout)) break; if (! recompile_files ()) break; if (tlink_verbose) fprintf (stderr, _("collect: relinking\n")); - exit = tlink_execute ("ld", ld_argv, ldout); + exit = tlink_execute ("ld", ld_argv, ldout, lderrout); } } - dump_file (ldout); + dump_file (ldout, stdout); unlink (ldout); + dump_file (lderrout, stderr); + unlink (lderrout); if (exit) { error ("ld returned %d exit status", exit);