X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftlink.c;h=6406615b5e3ec8a5d06caa665cf757f4fb365114;hb=ecbfdc878159c748742c4a5e8d416e4edd90cac9;hp=a3df317389f1896b40c2488c19922b2c02b29f36;hpb=e504db4a7d115668ff9ff0aebd7c819b2beb63c3;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tlink.c b/gcc/tlink.c index a3df317389f..6406615b5e3 100644 --- a/gcc/tlink.c +++ b/gcc/tlink.c @@ -1,49 +1,50 @@ /* Scan linker error messages for missing template instantiations and provide them. - Copyright (C) 1995, 1998 Free Software Foundation, Inc. + Copyright (C) 1995, 1998, 1999, 2000, 2001, 2003 + Free Software Foundation, Inc. Contributed by Jason Merrill (jason@cygnus.com). -This file is part of GNU CC. +This file is part of GCC. -GNU CC 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 version. +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 +version. -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +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 GNU CC; 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 COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. */ #include "config.h" #include "system.h" -#include "hash.h" +#include "coretypes.h" +#include "tm.h" +#include "intl.h" +#include "obstack.h" +#include "hashtab.h" #include "demangle.h" #include "collect2.h" #define MAX_ITERATIONS 17 -/* Obstack allocation and deallocation routines. */ -#define obstack_chunk_alloc xmalloc -#define obstack_chunk_free free - /* Defined in the automatically-generated underscore.c. */ extern int prepends_underscore; static int tlink_verbose; -/* Hash table boilerplate for working with hash.[ch]. We have hash tables +/* Hash table boilerplate for working with htab_t. We have hash tables for symbol names, file names, and demangled symbols. */ typedef struct symbol_hash_entry { - struct hash_entry root; + const char *key; struct file_hash_entry *file; int chosen; int tweaking; @@ -52,7 +53,7 @@ typedef struct symbol_hash_entry typedef struct file_hash_entry { - struct hash_entry root; + const char *key; const char *args; const char *dir; const char *main; @@ -61,150 +62,113 @@ typedef struct file_hash_entry typedef struct demangled_hash_entry { - struct hash_entry root; + const char *key; const char *mangled; } demangled; -static struct hash_table symbol_table; - -static struct hash_entry * symbol_hash_newfunc PARAMS ((struct hash_entry *, - struct hash_table *, - hash_table_key)); -static struct symbol_hash_entry * symbol_hash_lookup PARAMS ((const char *, - boolean)); -static struct hash_entry * file_hash_newfunc PARAMS ((struct hash_entry *, - struct hash_table *, - hash_table_key)); -static struct file_hash_entry * file_hash_lookup PARAMS ((const char *)); -static struct hash_entry * demangled_hash_newfunc PARAMS ((struct hash_entry *, - struct hash_table *, - hash_table_key)); -static struct demangled_hash_entry * - demangled_hash_lookup PARAMS ((const char *, boolean)); -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 *)); - -/* Create a new entry for the symbol hash table. - Passed to hash_table_init. */ - -static struct hash_entry * -symbol_hash_newfunc (entry, table, string) - struct hash_entry *entry; - struct hash_table *table; - hash_table_key string ATTRIBUTE_UNUSED; +/* Hash and comparison functions for these hash tables. */ + +static int hash_string_eq (const void *, const void *); +static hashval_t hash_string_hash (const void *); + +static int +hash_string_eq (const void *s1_p, const void *s2_p) { - struct symbol_hash_entry *ret = (struct symbol_hash_entry *) entry; - if (ret == NULL) - { - ret = ((struct symbol_hash_entry *) - hash_allocate (table, sizeof (struct symbol_hash_entry))); - if (ret == NULL) - return NULL; - } - ret->file = NULL; - ret->chosen = 0; - ret->tweaking = 0; - ret->tweaked = 0; - return (struct hash_entry *) ret; + const char *const *s1 = (const char *const *) s1_p; + const char *s2 = (const char *) s2_p; + return strcmp (*s1, s2) == 0; } -/* Look up an entry in the symbol hash table. */ - -static struct symbol_hash_entry * -symbol_hash_lookup (string, create) - const char *string; - boolean create; +static hashval_t +hash_string_hash (const void *s_p) { - return ((struct symbol_hash_entry *) - hash_lookup (&symbol_table, (const hash_table_key) string, - create, string_copy)); + const char *const *s = (const char *const *) s_p; + return (*htab_hash_string) (*s); } -static struct hash_table file_table; +static htab_t symbol_table; + +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 *); +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 *); -/* Create a new entry for the file hash table. - Passed to hash_table_init. */ +/* Look up an entry in the symbol hash table. */ -static struct hash_entry * -file_hash_newfunc (entry, table, string) - struct hash_entry *entry; - struct hash_table *table; - hash_table_key string ATTRIBUTE_UNUSED; +static struct symbol_hash_entry * +symbol_hash_lookup (const char *string, int create) { - struct file_hash_entry *ret = (struct file_hash_entry *) entry; - if (ret == NULL) + void **e; + e = htab_find_slot_with_hash (symbol_table, string, + (*htab_hash_string) (string), + create ? INSERT : NO_INSERT); + if (e == NULL) + return NULL; + if (*e == NULL) { - ret = ((struct file_hash_entry *) - hash_allocate (table, sizeof (struct file_hash_entry))); - if (ret == NULL) - return NULL; + struct symbol_hash_entry *v; + *e = v = xcalloc (1, sizeof (*v)); + v->key = xstrdup (string); } - ret->args = NULL; - ret->dir = NULL; - ret->main = NULL; - ret->tweaking = 0; - return (struct hash_entry *) ret; + return *e; } +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; -{ - return ((struct file_hash_entry *) - hash_lookup (&file_table, (const hash_table_key) string, true, - string_copy)); -} - -static struct hash_table demangled_table; - -/* Create a new entry for the demangled name hash table. - Passed to hash_table_init. */ - -static struct hash_entry * -demangled_hash_newfunc (entry, table, string) - struct hash_entry *entry; - struct hash_table *table; - hash_table_key string ATTRIBUTE_UNUSED; +file_hash_lookup (const char *string) { - struct demangled_hash_entry *ret = (struct demangled_hash_entry *) entry; - if (ret == NULL) + void **e; + e = htab_find_slot_with_hash (file_table, string, + (*htab_hash_string) (string), + INSERT); + if (*e == NULL) { - ret = ((struct demangled_hash_entry *) - hash_allocate (table, sizeof (struct demangled_hash_entry))); - if (ret == NULL) - return NULL; + struct file_hash_entry *v; + *e = v = xcalloc (1, sizeof (*v)); + v->key = xstrdup (string); } - ret->mangled = NULL; - return (struct hash_entry *) ret; + return *e; } +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; - boolean create; +demangled_hash_lookup (const char *string, int create) { - return ((struct demangled_hash_entry *) - hash_lookup (&demangled_table, (const hash_table_key) string, - create, string_copy)); + void **e; + e = htab_find_slot_with_hash (demangled_table, string, + (*htab_hash_string) (string), + create ? INSERT : NO_INSERT); + if (e == NULL) + return NULL; + if (*e == NULL) + { + struct demangled_hash_entry *v; + *e = v = xcalloc (1, sizeof (*v)); + v->key = xstrdup (string); + } + return *e; } /* Stack code. */ @@ -226,10 +190,9 @@ 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 + struct symbol_stack_entry *ep = obstack_alloc (&symbol_stack_obstack, sizeof (struct symbol_stack_entry)); ep->value = p; ep->next = symbol_stack; @@ -237,7 +200,7 @@ symbol_push (p) } static symbol * -symbol_pop () +symbol_pop (void) { struct symbol_stack_entry *ep = symbol_stack; symbol *p; @@ -250,15 +213,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 + ep = obstack_alloc (&file_stack_obstack, sizeof (struct file_stack_entry)); ep->value = p; ep->next = file_stack; @@ -267,7 +229,7 @@ file_push (p) } static file * -file_pop () +file_pop (void) { struct file_stack_entry *ep = file_stack; file *p; @@ -285,16 +247,17 @@ file_pop () /* Initialize the tlink machinery. Called from do_tlink. */ static void -tlink_init () +tlink_init (void) { const char *p; - hash_table_init (&symbol_table, symbol_hash_newfunc, string_hash, - string_compare); - hash_table_init (&file_table, file_hash_newfunc, string_hash, - string_compare); - hash_table_init (&demangled_table, demangled_hash_newfunc, - string_hash, string_compare); + symbol_table = htab_create (500, hash_string_hash, hash_string_eq, + NULL); + file_table = htab_create (500, hash_string_hash, hash_string_eq, + 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); @@ -312,24 +275,19 @@ tlink_init () } static int -tlink_execute (prog, argv, redir) - const char *prog; - char **argv; - const char *redir; +tlink_execute (const char *prog, char **argv, const char *redir) { collect_execute (prog, argv, redir); return collect_wait (prog); -} +} static char * -frob_extension (s, ext) - const char *s; - const char *ext; +frob_extension (const char *s, const char *ext) { - const char *p = rindex (s, '/'); + const char *p = strrchr (s, '/'); if (! p) p = s; - p = rindex (p, '.'); + p = strrchr (p, '.'); if (! p) p = s + strlen (s); @@ -338,9 +296,7 @@ frob_extension (s, 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') @@ -352,32 +308,27 @@ obstack_fgets (stream, ob) } 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 obstack_fgets (stream, &permanent_obstack); + return xstrdup (tfgets (stream)); } /* Real tlink code. */ /* 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; @@ -417,15 +368,13 @@ 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 ((char*) f->root.key, "r"); + FILE *stream = fopen (f->key, "r"); if (tlink_verbose >= 2) - fprintf (stderr, "collect: reading %s\n", - (char*) f->root.key); + fprintf (stderr, _("collect: reading %s\n"), f->key); while (fscanf (stream, "%c ", &c) == 1) { @@ -465,9 +414,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); @@ -490,15 +437,18 @@ maybe_tweak (line, f) XXX Should this use collect_execute instead of system? */ static int -recompile_files () +recompile_files (void) { file *f; + putenv (xstrdup ("COMPILER_PATH=")); + putenv (xstrdup ("LIBRARY_PATH=")); + while ((f = file_pop ()) != NULL) { char *line, *command; - FILE *stream = fopen ((char*) f->root.key, "r"); - const char *outname = frob_extension ((char*) f->root.key, ".rnw"); + FILE *stream = fopen (f->key, "r"); + const char *const outname = frob_extension (f->key, ".rnw"); FILE *output = fopen (outname, "w"); while ((line = tfgets (stream)) != NULL) @@ -513,7 +463,7 @@ recompile_files () } fclose (stream); fclose (output); - rename (outname, (char*) f->root.key); + rename (outname, f->key); obstack_grow (&temporary_obstack, "cd ", 3); obstack_grow (&temporary_obstack, f->dir, strlen (f->dir)); @@ -525,7 +475,7 @@ recompile_files () command = obstack_copy0 (&temporary_obstack, f->main, strlen (f->main)); if (tlink_verbose) - fprintf (stderr, "collect: recompiling %s\n", f->main); + fprintf (stderr, _("collect: recompiling %s\n"), f->main); if (tlink_verbose >= 3) fprintf (stderr, "%s\n", command); @@ -543,16 +493,21 @@ 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; for (; *object; object++) { - const char *p = frob_extension (*object, ".rpo"); + const char *p; file *f; + /* Don't bother trying for ld flags. */ + if (*object[0] == '-') + continue; + + p = frob_extension (*object, ".rpo"); + if (! file_exists (p)) continue; @@ -570,21 +525,20 @@ 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; while ((sym = symbol_pop ()) != NULL) { demangled *dem; - const char *p = cplus_demangle ((char*) sym->root.key, - DMGL_PARAMS | DMGL_ANSI); + const char *p = cplus_demangle (sym->key, DMGL_PARAMS | DMGL_ANSI); if (! p) continue; dem = demangled_hash_lookup (p, true); - dem->mangled = (char*) sym->root.key; + dem->mangled = sym->key; } } @@ -592,8 +546,7 @@ 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; @@ -603,51 +556,88 @@ scan_linker_output (fname) char *p = line, *q; symbol *sym; int end; - - while (*p && ISSPACE ((unsigned char)*p)) + + while (*p && ISSPACE ((unsigned char) *p)) ++p; if (! *p) continue; - for (q = p; *q && ! ISSPACE ((unsigned char)*q); ++q) + for (q = p; *q && ! ISSPACE ((unsigned char) *q); ++q) ; /* Try the first word on the line. */ if (*p == '.') ++p; - if (*p == '_' && prepends_underscore) - ++p; + if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX))) + p += strlen (USER_LABEL_PREFIX); end = ! *q; *q = 0; sym = symbol_hash_lookup (p, false); + /* Some SVR4 linkers produce messages like + ld: 0711-317 ERROR: Undefined symbol: .g__t3foo1Zi + */ + if (! sym && ! end && strstr (q + 1, "Undefined symbol: ")) + { + char *p = strrchr (q + 1, ' '); + p++; + if (*p == '.') + p++; + if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX))) + p += strlen (USER_LABEL_PREFIX); + sym = symbol_hash_lookup (p, false); + } + if (! sym && ! end) /* Try a mangled name in quotes. */ { - const char *oldq = q+1; + const char *oldq = q + 1; demangled *dem = 0; q = 0; /* First try `GNU style'. */ - p = index (oldq, '`'); + p = strchr (oldq, '`'); if (p) - p++, q = index (p, '\''); + p++, q = strchr (p, '\''); /* Then try "double quotes". */ - else if (p = index (oldq, '"'), p) - p++, q = index (p, '"'); + 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; + } + + if (p) + { + /* Don't let the strstr's below see the demangled name; we + might get spurious matches. */ + p[-1] = '\0'; - if (q) + /* 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") + || strstr (oldq, "nresolved") + || strstr (oldq, "nsatisfied") + || strstr (oldq, "ultiple"))) { *q = 0; dem = demangled_hash_lookup (p, false); if (dem) sym = symbol_hash_lookup (dem->mangled, false); else - { - if (*p == '_' && prepends_underscore) - ++p; + { + if (!strncmp (p, USER_LABEL_PREFIX, + strlen (USER_LABEL_PREFIX))) + p += strlen (USER_LABEL_PREFIX); sym = symbol_hash_lookup (p, false); } } @@ -661,12 +651,12 @@ scan_linker_output (fname) if (sym && !sym->tweaking) { if (tlink_verbose >= 2) - fprintf (stderr, "collect: tweaking %s in %s\n", - (char*) sym->root.key, (char*) sym->file->root.key); + fprintf (stderr, _("collect: tweaking %s in %s\n"), + sym->key, sym->file->key); sym->tweaking = 1; file_push (sym->file); } - + obstack_free (&temporary_obstack, temporary_firstobj); } @@ -684,8 +674,7 @@ 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); @@ -708,7 +697,7 @@ do_tlink (ld_argv, object_lst) if (! recompile_files ()) break; if (tlink_verbose) - fprintf (stderr, "collect: relinking\n"); + fprintf (stderr, _("collect: relinking\n")); exit = tlink_execute ("ld", ld_argv, ldout); } }