X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fcollect2.c;h=aed4c6758600a68f68039f7805edeca4199e839a;hp=2d49cce3ffeedce3f01a57a82e73cbcea5a92072;hb=ecf52e84f7bdece8bbe021791ea304e9679db10f;hpb=ff2185fbe6ac8c9927c341918a764e79f76f76d2 diff --git a/gcc/collect2.c b/gcc/collect2.c index 2d49cce3ffe..aed4c675860 100644 --- a/gcc/collect2.c +++ b/gcc/collect2.c @@ -1,7 +1,8 @@ /* Collect static initialization info into data structures that can be traversed by C++ initialization and finalization routines. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009 + Free Software Foundation, Inc. Contributed by Chris Smith (csmith@convex.com). Heavily modified by Michael Meissner (meissner@cygnus.com), Per Bothner (bothner@cygnus.com), and John Gilmore (gnu@cygnus.com). @@ -10,7 +11,7 @@ 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 @@ -19,9 +20,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 +. */ /* Build tables of static constructors and destructors and run ld. */ @@ -35,19 +35,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA # define SIGCHLD SIGCLD #endif -#ifdef vfork /* Autoconf may define this to fork for us. */ -# define VFORK_STRING "fork" -#else -# define VFORK_STRING "vfork" -#endif -#ifdef HAVE_VFORK_H -#include -#endif -#ifdef VMS -#define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \ - lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1) -#endif /* VMS */ - #ifndef LIBRARY_PATH_ENV #define LIBRARY_PATH_ENV "LIBRARY_PATH" #endif @@ -55,6 +42,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #define COLLECT #include "collect2.h" +#include "collect2-aix.h" #include "demangle.h" #include "obstack.h" #include "intl.h" @@ -66,9 +54,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA the utilities are not correct for a cross-compiler; we have to hope that cross-versions are in the proper directories. */ -#ifdef CROSS_COMPILE -#undef SUNOS4_SHARED_LIBRARIES +#ifdef CROSS_DIRECTORY_STRUCTURE +#ifndef CROSS_AIX_SUPPORT #undef OBJECT_FORMAT_COFF +#endif #undef MD_EXEC_PREFIX #undef REAL_LD_FILE_NAME #undef REAL_NM_FILE_NAME @@ -86,6 +75,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #ifdef OBJECT_FORMAT_COFF +#ifndef CROSS_DIRECTORY_STRUCTURE #include #include @@ -100,6 +90,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #endif #include +#endif /* Some systems have an ISCOFF macro, but others do not. In some cases the macro may be wrong. MY_ISCOFF is defined in tm.h files for machines @@ -140,20 +131,20 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA fprintf ((STREAM), "void _GLOBAL__DD() {\n\t%s();\n}\n", (FUNC)) #endif -#if defined (LDD_SUFFIX) || SUNOS4_SHARED_LIBRARIES +#ifdef LDD_SUFFIX #define SCAN_LIBRARIES #endif +#ifndef SHLIB_SUFFIX +#define SHLIB_SUFFIX ".so" +#endif + #ifdef USE_COLLECT2 int do_collecting = 1; #else int do_collecting = 0; #endif -#ifndef COLLECT_PARSE_FLAG -#define COLLECT_PARSE_FLAG(FLAG) -#endif - /* Nonzero if we should suppress the automatic demangling of identifiers in linker error messages. Set from COLLECT_NO_DEMANGLE. */ int no_demangle; @@ -179,35 +170,38 @@ struct head enum pass { PASS_FIRST, /* without constructors */ PASS_OBJ, /* individual objects */ - PASS_LIB, /* looking for shared libraries */ + PASS_LIB, /* looking for shared libraries */ PASS_SECOND /* with constructors linked in */ }; int vflag; /* true if -v */ static int rflag; /* true if -r */ static int strip_flag; /* true if -s */ +static const char *demangle_flag; #ifdef COLLECT_EXPORT_LIST static int export_flag; /* true if -bE */ static int aix64_flag; /* true if -b64 */ +static int aixrtl_flag; /* true if -brtl */ #endif int debug; /* true if -debug */ -static int shared_obj; /* true if -shared */ +static int shared_obj; /* true if -shared */ static const char *c_file; /* .c for constructor/destructor list. */ static const char *o_file; /* .o for constructor/destructor list. */ #ifdef COLLECT_EXPORT_LIST -static const char *export_file; /* .x for AIX export list. */ +static const char *export_file; /* .x for AIX export list. */ #endif -const char *ldout; /* File for ld errors. */ +const char *ldout; /* File for ld stdout. */ +const char *lderrout; /* File for ld stderr. */ static const char *output_file; /* Output file for ld. */ static const char *nm_file_name; /* pathname of nm */ #ifdef LDD_SUFFIX static const char *ldd_file_name; /* pathname of ldd (or equivalent) */ #endif static const char *strip_file_name; /* pathname of strip */ -const char *c_file_name; /* pathname of gcc */ +const char *c_file_name; /* pathname of gcc */ static char *initname, *fininame; /* names of init and fini funcs */ static struct head constructors; /* list of constructors found */ @@ -217,11 +211,19 @@ static struct head exports; /* list of exported symbols */ #endif static struct head frame_tables; /* list of frame unwind info tables */ +static bool at_file_supplied; /* Whether to use @file arguments */ +static char *response_file; /* Name of any current response file */ + struct obstack temporary_obstack; char * temporary_firstobj; -/* Holds the return value of pexecute and fork. */ -int pid; +/* A string that must be prepended to a target OS path in order to find + it on the host system. */ +#ifdef TARGET_SYSTEM_ROOT +static const char *target_system_root = TARGET_SYSTEM_ROOT; +#else +static const char *target_system_root = ""; +#endif /* Structure to hold all the directories in which to search for files to execute. */ @@ -246,16 +248,28 @@ static struct path_prefix cmdline_lib_dirs; /* directories specified with -L */ static struct path_prefix libpath_lib_dirs; /* directories in LIBPATH */ static struct path_prefix *libpaths[3] = {&cmdline_lib_dirs, &libpath_lib_dirs, NULL}; -static const char *const libexts[3] = {"a", "so", NULL}; /* possible library extensions */ #endif +/* Special kinds of symbols that a name may denote. */ + +typedef enum { + SYM_REGULAR = 0, /* nothing special */ + + SYM_CTOR = 1, /* constructor */ + SYM_DTOR = 2, /* destructor */ + SYM_INIT = 3, /* shared object routine that calls all the ctors */ + SYM_FINI = 4, /* shared object routine that calls all the dtors */ + SYM_DWEH = 5 /* DWARF exception handling table */ +} symkind; + +static symkind is_ctor_dtor (const char *); + static void handler (int); -static int is_ctor_dtor (const char *); static char *find_a_file (struct path_prefix *, const char *); static void add_prefix (struct path_prefix *, const char *); static void prefix_from_env (const char *, struct path_prefix *); static void prefix_from_string (const char *, struct path_prefix *); -static void do_wait (const char *); +static void do_wait (const char *, struct pex_obj *); static void fork_execute (const char *, char **); static void maybe_unlink (const char *); static void add_to_list (struct head *, const char *); @@ -290,26 +304,6 @@ static char *resolve_lib_name (const char *); #endif static char *extract_string (const char **); -#ifndef HAVE_DUP2 -static int -dup2 (int oldfd, int newfd) -{ - int fdtmp[256]; - int fdx = 0; - int fd; - - if (oldfd == newfd) - return oldfd; - close (newfd); - while ((fd = dup (oldfd)) != newfd && fd >= 0) /* good enough for low fd's */ - fdtmp[fdx++] = fd; - while (fdx > 0) - close (fdtmp[--fdx]); - - return fd; -} -#endif /* ! HAVE_DUP2 */ - /* Delete tempfiles and exit function. */ void @@ -328,39 +322,48 @@ collect_exit (int status) if (ldout != 0 && ldout[0]) { - dump_file (ldout); + dump_file (ldout, stdout); maybe_unlink (ldout); } + if (lderrout != 0 && lderrout[0]) + { + dump_file (lderrout, stderr); + maybe_unlink (lderrout); + } + if (status != 0 && output_file != 0 && output_file[0]) maybe_unlink (output_file); + if (response_file) + maybe_unlink (response_file); + exit (status); } /* Notify user of a non-error. */ void -notice (const char *msgid, ...) +notice (const char *cmsgid, ...) { va_list ap; - va_start (ap, msgid); - vfprintf (stderr, _(msgid), ap); + va_start (ap, cmsgid); + vfprintf (stderr, _(cmsgid), ap); va_end (ap); } /* Die when sys call fails. */ void -fatal_perror (const char * msgid, ...) +fatal_perror (const char * cmsgid, ...) { int e = errno; va_list ap; - va_start (ap, msgid); + va_start (ap, cmsgid); fprintf (stderr, "collect2: "); - vfprintf (stderr, _(msgid), ap); + vfprintf (stderr, _(cmsgid), ap); fprintf (stderr, ": %s\n", xstrerror (e)); va_end (ap); @@ -370,13 +373,13 @@ fatal_perror (const char * msgid, ...) /* Just die. */ void -fatal (const char * msgid, ...) +fatal (const char * cmsgid, ...) { va_list ap; - va_start (ap, msgid); + va_start (ap, cmsgid); fprintf (stderr, "collect2: "); - vfprintf (stderr, _(msgid), ap); + vfprintf (stderr, _(cmsgid), ap); fprintf (stderr, "\n"); va_end (ap); @@ -386,13 +389,13 @@ fatal (const char * msgid, ...) /* Write error message. */ void -error (const char * msgid, ...) +error (const char * gmsgid, ...) { va_list ap; - va_start (ap, msgid); + va_start (ap, gmsgid); fprintf (stderr, "collect2: "); - vfprintf (stderr, _(msgid), ap); + vfprintf (stderr, _(gmsgid), ap); fprintf (stderr, "\n"); va_end(ap); } @@ -401,9 +404,9 @@ error (const char * msgid, ...) provide a default entry. */ void -fancy_abort (void) +fancy_abort (const char *file, int line, const char *func) { - fatal ("internal error"); + fatal ("internal gcc abort in %s, at %s:%d", func, file, line); } static void @@ -418,13 +421,19 @@ handler (int signo) if (ldout != 0 && ldout[0]) maybe_unlink (ldout); + if (lderrout != 0 && lderrout[0]) + maybe_unlink (lderrout); + #ifdef COLLECT_EXPORT_LIST if (export_file != 0 && export_file[0]) maybe_unlink (export_file); #endif + if (response_file) + maybe_unlink (response_file); + signal (signo, SIG_DFL); - kill (getpid (), signo); + raise (signo); } @@ -463,11 +472,11 @@ extract_string (const char **pp) obstack_1grow (&temporary_obstack, '\0'); *pp = p; - return obstack_finish (&temporary_obstack); + return XOBFINISH (&temporary_obstack, char *); } void -dump_file (const char *name) +dump_file (const char *name, FILE *to) { FILE *stream = fopen (name, "r"); @@ -484,54 +493,65 @@ dump_file (const char *name) const char *word, *p; char *result; obstack_1grow (&temporary_obstack, '\0'); - word = obstack_finish (&temporary_obstack); + word = XOBFINISH (&temporary_obstack, const char *); if (*word == '.') - ++word, putc ('.', stderr); + ++word, putc ('.', to); p = word; if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX))) p += strlen (USER_LABEL_PREFIX); +#ifdef HAVE_LD_DEMANGLE + result = 0; +#else if (no_demangle) result = 0; else result = cplus_demangle (p, DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE); +#endif if (result) { int diff; - fputs (result, stderr); + fputs (result, to); diff = strlen (word) - strlen (result); while (diff > 0 && c == ' ') - --diff, putc (' ', stderr); - while (diff < 0 && c == ' ') - ++diff, c = getc (stream); + --diff, putc (' ', to); + if (diff < 0 && c == ' ') + { + while (diff < 0 && c == ' ') + ++diff, c = getc (stream); + if (!ISSPACE (c)) + { + /* Make sure we output at least one space, or + the demangled symbol name will run into + whatever text follows. */ + putc (' ', to); + } + } free (result); } else - fputs (word, stderr); + fputs (word, to); - fflush (stderr); + fflush (to); obstack_free (&temporary_obstack, temporary_firstobj); } if (c == EOF) break; - putc (c, stderr); + putc (c, to); } fclose (stream); } -/* Decide whether the given symbol is: a constructor (1), a destructor - (2), a routine in a shared object that calls all the constructors - (3) or destructors (4), a DWARF exception-handling table (5), or - nothing special (0). */ +/* Return the kind of symbol denoted by name S. */ -static int +static symkind is_ctor_dtor (const char *s) { - struct names { const char *const name; const int len; const int ret; + struct names { const char *const name; const int len; symkind ret; const int two_underscores; }; const struct names *p; @@ -540,27 +560,27 @@ is_ctor_dtor (const char *s) static const struct names special[] = { #ifndef NO_DOLLAR_IN_LABEL - { "GLOBAL__I$", sizeof ("GLOBAL__I$")-1, 1, 0 }, - { "GLOBAL__D$", sizeof ("GLOBAL__D$")-1, 2, 0 }, + { "GLOBAL__I$", sizeof ("GLOBAL__I$")-1, SYM_CTOR, 0 }, + { "GLOBAL__D$", sizeof ("GLOBAL__D$")-1, SYM_DTOR, 0 }, #else #ifndef NO_DOT_IN_LABEL - { "GLOBAL__I.", sizeof ("GLOBAL__I.")-1, 1, 0 }, - { "GLOBAL__D.", sizeof ("GLOBAL__D.")-1, 2, 0 }, + { "GLOBAL__I.", sizeof ("GLOBAL__I.")-1, SYM_CTOR, 0 }, + { "GLOBAL__D.", sizeof ("GLOBAL__D.")-1, SYM_DTOR, 0 }, #endif /* NO_DOT_IN_LABEL */ #endif /* NO_DOLLAR_IN_LABEL */ - { "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, 1, 0 }, - { "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, 2, 0 }, - { "GLOBAL__F_", sizeof ("GLOBAL__F_")-1, 5, 0 }, - { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, 3, 0 }, - { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, 4, 0 }, - { NULL, 0, 0, 0 } + { "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, SYM_CTOR, 0 }, + { "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, SYM_DTOR, 0 }, + { "GLOBAL__F_", sizeof ("GLOBAL__F_")-1, SYM_DWEH, 0 }, + { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, SYM_INIT, 0 }, + { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, SYM_FINI, 0 }, + { NULL, 0, SYM_REGULAR, 0 } }; while ((ch = *s) == '_') ++s; if (s == orig_s) - return 0; + return SYM_REGULAR; for (p = &special[0]; p->len > 0; p++) { @@ -571,7 +591,7 @@ is_ctor_dtor (const char *s) return p->ret; } } - return 0; + return SYM_REGULAR; } /* We maintain two prefix lists: one from COMPILER_PATH environment variable @@ -579,7 +599,7 @@ is_ctor_dtor (const char *s) static struct path_prefix cpath, path; -#ifdef CROSS_COMPILE +#ifdef CROSS_DIRECTORY_STRUCTURE /* This is the name of the target machine. We use it to form the name of the files to execute. */ @@ -605,15 +625,11 @@ find_a_file (struct path_prefix *pprefix, const char *name) len += strlen (HOST_EXECUTABLE_SUFFIX); #endif - temp = xmalloc (len); + temp = XNEWVEC (char, len); /* Determine the filename to execute (special case for absolute paths). */ - if (*name == '/' -#ifdef HAVE_DOS_BASED_FILE_SYSTEM - || (*name && name[1] == ':') -#endif - ) + if (IS_ABSOLUTE_PATH (name)) { if (access (name, X_OK) == 0) { @@ -693,7 +709,7 @@ add_prefix (struct path_prefix *pprefix, const char *prefix) if (len > pprefix->max_len) pprefix->max_len = len; - pl = xmalloc (sizeof (struct prefix_list)); + pl = XNEW (struct prefix_list); pl->prefix = xstrdup (prefix); if (*prev) @@ -720,7 +736,7 @@ static void prefix_from_string (const char *p, struct path_prefix *pprefix) { const char *startp, *endp; - char *nstore = xmalloc (strlen (p) + 3); + char *nstore = XNEWVEC (char, strlen (p) + 3); if (debug) fprintf (stderr, "Convert string '%s' into prefixes, separator = '%c'\n", p, PATH_SEPARATOR); @@ -754,6 +770,7 @@ prefix_from_string (const char *p, struct path_prefix *pprefix) else endp++; } + free (nstore); } /* Main program. */ @@ -772,7 +789,7 @@ main (int argc, char **argv) static const char *const strip_suffix = "strip"; static const char *const gstrip_suffix = "gstrip"; -#ifdef CROSS_COMPILE +#ifdef CROSS_DIRECTORY_STRUCTURE /* If we look for a program in the compiler directories, we just use the short name, since these directories are already system-specific. But it we look for a program in the system directories, we need to @@ -801,7 +818,7 @@ main (int argc, char **argv) #endif const char *const full_strip_suffix = strip_suffix; const char *const full_gstrip_suffix = gstrip_suffix; -#endif /* CROSS_COMPILE */ +#endif /* CROSS_DIRECTORY_STRUCTURE */ const char *arg; FILE *outf; @@ -819,7 +836,15 @@ main (int argc, char **argv) char **object_lst; const char **object; int first_file; - int num_c_args = argc+9; + int num_c_args; + char **old_argv; + + old_argv = argv; + expandargv (&argc, &argv); + if (argv != old_argv) + at_file_supplied = 1; + + num_c_args = argc + 9; no_demangle = !! getenv ("COLLECT_NO_DEMANGLE"); @@ -837,14 +862,20 @@ main (int argc, char **argv) signal (SIGCHLD, SIG_DFL); #endif + /* Unlock the stdio streams. */ + unlock_std_streams (); + gcc_init_libintl (); /* Do not invoke xcalloc before this point, since locale needs to be set first, in case a diagnostic is issued. */ - ld1 = (const char **)(ld1_argv = xcalloc(sizeof (char *), argc+3)); - ld2 = (const char **)(ld2_argv = xcalloc(sizeof (char *), argc+10)); - object = (const char **)(object_lst = xcalloc(sizeof (char *), argc)); + ld1_argv = XCNEWVEC (char *, argc + 4); + ld1 = CONST_CAST2 (const char **, char **, ld1_argv); + ld2_argv = XCNEWVEC (char *, argc + 11); + ld2 = CONST_CAST2 (const char **, char **, ld2_argv); + object_lst = XCNEWVEC (char *, argc); + object = CONST_CAST2 (const char **, char **, object_lst); #ifdef DEBUG debug = 1; @@ -860,7 +891,6 @@ main (int argc, char **argv) { if (! strcmp (argv[i], "-debug")) debug = 1; - COLLECT_PARSE_FLAG (argv[i]); } vflag = debug; } @@ -872,9 +902,11 @@ main (int argc, char **argv) #endif obstack_begin (&temporary_obstack, 0); - temporary_firstobj = obstack_alloc (&temporary_obstack, 0); + temporary_firstobj = (char *) obstack_alloc (&temporary_obstack, 0); +#ifndef HAVE_LD_DEMANGLE current_demangling_style = auto_demangling; +#endif p = getenv ("COLLECT_GCC_OPTIONS"); while (p && *p) { @@ -884,10 +916,12 @@ main (int argc, char **argv) } obstack_free (&temporary_obstack, temporary_firstobj); - /* -fno-exceptions -w */ - num_c_args += 2; + /* -fno-profile-arcs -fno-test-coverage -fno-branch-probabilities + -fno-exceptions -w */ + num_c_args += 5; - c_ptr = (const char **) (c_argv = xcalloc (sizeof (char *), num_c_args)); + c_argv = XCNEWVEC (char *, num_c_args); + c_ptr = CONST_CAST2 (const char **, char **, c_argv); if (argc < 2) fatal ("no arguments"); @@ -978,7 +1012,7 @@ main (int argc, char **argv) c_file_name = getenv ("COLLECT_GCC"); if (c_file_name == 0) { -#ifdef CROSS_COMPILE +#ifdef CROSS_DIRECTORY_STRUCTURE c_file_name = concat (target_machine, "-gcc", NULL); #else c_file_name = "gcc"; @@ -1004,6 +1038,7 @@ main (int argc, char **argv) export_file = make_temp_file (".x"); #endif ldout = make_temp_file (".ld"); + lderrout = make_temp_file (".le"); *c_ptr++ = c_file_name; *c_ptr++ = "-x"; *c_ptr++ = "c"; @@ -1046,6 +1081,9 @@ main (int argc, char **argv) } } obstack_free (&temporary_obstack, temporary_firstobj); + *c_ptr++ = "-fno-profile-arcs"; + *c_ptr++ = "-fno-test-coverage"; + *c_ptr++ = "-fno-branch-probabilities"; *c_ptr++ = "-fno-exceptions"; *c_ptr++ = "-w"; @@ -1060,6 +1098,12 @@ main (int argc, char **argv) /* After the first file, put in the c++ rt0. */ first_file = 1; +#ifdef HAVE_LD_DEMANGLE + if (!demangle_flag && !no_demangle) + demangle_flag = "--demangle"; + if (demangle_flag) + *ld1++ = *ld2++ = demangle_flag; +#endif while ((arg = *++argv) != (char *) 0) { *ld1++ = *ld2++ = arg; @@ -1073,9 +1117,11 @@ main (int argc, char **argv) explicitly puts an export list in command line */ case 'b': if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0) - export_flag = 1; + export_flag = 1; else if (arg[2] == '6' && arg[3] == '4') aix64_flag = 1; + else if (arg[2] == 'r' && arg[3] == 't' && arg[4] == 'l') + aixrtl_flag = 1; break; #endif @@ -1086,6 +1132,11 @@ main (int argc, char **argv) ld1--; ld2--; } + if (!strcmp (arg, "-dynamic-linker") && argv[1]) + { + ++argv; + *ld1++ = *ld2++ = *argv; + } break; case 'l': @@ -1099,7 +1150,7 @@ main (int argc, char **argv) } #ifdef COLLECT_EXPORT_LIST { - /* Resolving full library name. */ + /* Resolving full library name. */ const char *s = resolve_lib_name (arg+2); /* Saving a full library name. */ @@ -1116,7 +1167,9 @@ main (int argc, char **argv) #else #if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES case 'L': - if (is_in_args (arg, (const char **) ld1_argv, ld1-1)) + if (is_in_args (arg, + CONST_CAST2 (const char **, char **, ld1_argv), + ld1 - 1)) --ld1; break; #endif /* LINK_ELIMINATE_DUPLICATE_LDIRECTORIES */ @@ -1154,6 +1207,36 @@ main (int argc, char **argv) if (arg[2] == '\0') vflag = 1; break; + + case '-': + if (strcmp (arg, "--no-demangle") == 0) + { + demangle_flag = arg; + no_demangle = 1; + ld1--; + ld2--; + } + else if (strncmp (arg, "--demangle", 10) == 0) + { + demangle_flag = arg; + no_demangle = 0; +#ifndef HAVE_LD_DEMANGLE + if (arg[10] == '=') + { + enum demangling_styles style + = cplus_demangle_name_to_style (arg+11); + if (style == unknown_demangling) + error ("unknown demangling style '%s'", arg+11); + else + current_demangling_style = style; + } +#endif + ld1--; + ld2--; + } + else if (strncmp (arg, "--sysroot=", 10) == 0) + target_system_root = arg + 10; + break; } } else if ((p = strrchr (arg, '.')) != (char *) 0 @@ -1181,8 +1264,8 @@ main (int argc, char **argv) else { /* Saving a full library name. */ - add_to_list (&libs, arg); - } + add_to_list (&libs, arg); + } #endif } } @@ -1198,7 +1281,8 @@ main (int argc, char **argv) /* The AIX linker will discard static constructors in object files if nothing else in the file is referenced, so look at them first. */ { - const char **export_object_lst = (const char **)object_lst; + const char **export_object_lst + = CONST_CAST2 (const char **, char **, object_lst); while (export_object_lst < object) scan_prog_file (*export_object_lst++, PASS_OBJ); @@ -1343,8 +1427,9 @@ main (int argc, char **argv) /* Strip now if it was requested on the command line. */ if (strip_flag) { - char **real_strip_argv = xcalloc (sizeof (char *), 3); - const char ** strip_argv = (const char **) real_strip_argv; + char **real_strip_argv = XCNEWVEC (char *, 3); + const char ** strip_argv = CONST_CAST2 (const char **, char **, + real_strip_argv); strip_argv[0] = strip_file_name; strip_argv[1] = output_file; @@ -1394,10 +1479,12 @@ main (int argc, char **argv) if (! exports.first) *ld2++ = concat ("-bE:", export_file, NULL); +#ifndef LD_INIT_SWITCH add_to_list (&exports, initname); add_to_list (&exports, fininame); add_to_list (&exports, "_GLOBAL__DI"); add_to_list (&exports, "_GLOBAL__DD"); +#endif exportf = fopen (export_file, "w"); if (exportf == (FILE *) 0) fatal_perror ("fopen %s", export_file); @@ -1428,10 +1515,10 @@ main (int argc, char **argv) fork_execute ("gcc", c_argv); #ifdef COLLECT_EXPORT_LIST - /* On AIX we must call tlink because of possible templates resolution */ + /* On AIX we must call tlink because of possible templates resolution. */ do_tlink (ld2_argv, object_lst); #else - /* Otherwise, simply call ld because tlink is already done */ + /* Otherwise, simply call ld because tlink is already done. */ fork_execute ("ld", ld2_argv); /* Let scan_prog_file do any final mods (OSF/rose needs this for @@ -1453,11 +1540,14 @@ main (int argc, char **argv) /* Wait for a process to finish, and exit if a nonzero status is found. */ int -collect_wait (const char *prog) +collect_wait (const char *prog, struct pex_obj *pex) { int status; - pwait (pid, &status, 0); + if (!pex_get_status (pex, 1, &status)) + fatal_perror ("can't get program status"); + pex_free (pex); + if (status) { if (WIFSIGNALED (status)) @@ -1476,27 +1566,73 @@ collect_wait (const char *prog) } static void -do_wait (const char *prog) +do_wait (const char *prog, struct pex_obj *pex) { - int ret = collect_wait (prog); + int ret = collect_wait (prog, pex); if (ret != 0) { error ("%s returned %d exit status", prog, ret); collect_exit (ret); } + + if (response_file) + { + unlink (response_file); + response_file = NULL; + } } /* Execute a program, and wait for the reply. */ -void -collect_execute (const char *prog, char **argv, const char *redir) +struct pex_obj * +collect_execute (const char *prog, char **argv, const char *outname, + const char *errname) { - char *errmsg_fmt; - char *errmsg_arg; - int redir_handle = -1; - int stdout_save = -1; - int stderr_save = -1; + struct pex_obj *pex; + const char *errmsg; + int err; + char *response_arg = NULL; + char *response_argv[3] ATTRIBUTE_UNUSED; + + if (HAVE_GNU_LD && at_file_supplied && argv[0] != NULL) + { + /* If using @file arguments, create a temporary file and put the + contents of argv into it. Then change argv to an array corresponding + to a single argument @FILE, where FILE is the temporary filename. */ + + char **current_argv = argv + 1; + char *argv0 = argv[0]; + int status; + FILE *f; + + /* Note: we assume argv contains at least one element; this is + checked above. */ + + response_file = make_temp_file (""); + + f = fopen (response_file, "w"); + + if (f == NULL) + fatal ("could not open response file %s", response_file); + + status = writeargv (current_argv, f); + + if (status) + fatal ("could not write to response file %s", response_file); + + status = fclose (f); + + if (EOF == status) + fatal ("could not close response file %s", response_file); + + response_arg = concat ("@", response_file, NULL); + response_argv[0] = argv0; + response_argv[1] = response_arg; + response_argv[2] = NULL; + + argv = response_argv; + } if (vflag || debug) { @@ -1521,49 +1657,38 @@ collect_execute (const char *prog, char **argv, const char *redir) since we might not end up needing something that we could not find. */ if (argv[0] == 0) - fatal ("cannot find `%s'", prog); + fatal ("cannot find '%s'", prog); - if (redir) - { - /* Open response file. */ - redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT); - - /* Duplicate the stdout and stderr file handles - so they can be restored later. */ - stdout_save = dup (STDOUT_FILENO); - if (stdout_save == -1) - fatal_perror ("redirecting stdout: %s", redir); - stderr_save = dup (STDERR_FILENO); - if (stderr_save == -1) - fatal_perror ("redirecting stdout: %s", redir); - - /* Redirect stdout & stderr to our response file. */ - dup2 (redir_handle, STDOUT_FILENO); - dup2 (redir_handle, STDERR_FILENO); - } + pex = pex_init (0, "collect2", NULL); + if (pex == NULL) + fatal_perror ("pex_init failed"); - pid = pexecute (argv[0], argv, argv[0], NULL, &errmsg_fmt, &errmsg_arg, - (PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH)); - - if (redir) + errmsg = pex_run (pex, PEX_LAST | PEX_SEARCH, argv[0], argv, outname, + errname, &err); + if (errmsg != NULL) { - /* Restore stdout and stderr to their previous settings. */ - dup2 (stdout_save, STDOUT_FILENO); - dup2 (stderr_save, STDERR_FILENO); - - /* Close response file. */ - close (redir_handle); + if (err != 0) + { + errno = err; + fatal_perror (errmsg); + } + else + fatal (errmsg); } - if (pid == -1) - fatal_perror (errmsg_fmt, errmsg_arg); + if (response_arg) + free (response_arg); + + return pex; } static void fork_execute (const char *prog, char **argv) { - collect_execute (prog, argv, NULL); - do_wait (prog); + struct pex_obj *pex; + + pex = collect_execute (prog, argv, NULL, NULL); + do_wait (prog, pex); } /* Unlink a file unless we are debugging. */ @@ -1572,7 +1697,7 @@ static void maybe_unlink (const char *file) { if (!debug) - unlink (file); + unlink_if_ordinary (file); else notice ("[Leaving %s]\n", file); } @@ -1585,7 +1710,8 @@ static long sequence_number = 0; static void add_to_list (struct head *head_ptr, const char *name) { - struct id *newid = xcalloc (sizeof (struct id) + strlen (name), 1); + struct id *newid + = (struct id *) xcalloc (sizeof (struct id) + strlen (name), 1); struct id *p; strcpy (newid->name, name); @@ -1656,7 +1782,7 @@ sort_ids (struct head *head_ptr) || id->sequence > (*id_ptr)->sequence /* Hack: do lexical compare, too. || (id->sequence == (*id_ptr)->sequence - && strcmp (id->name, (*id_ptr)->name) > 0) */ + && strcmp (id->name, (*id_ptr)->name) > 0) */ ) { id->next = *id_ptr; @@ -1777,9 +1903,9 @@ write_c_file_stat (FILE *stream, const char *name ATTRIBUTE_UNUSED) } else { - if (strncmp (q, ".so", 3) == 0) + if (strncmp (q, SHLIB_SUFFIX, strlen (SHLIB_SUFFIX)) == 0) { - q += 3; + q += strlen (SHLIB_SUFFIX); break; } else @@ -1787,7 +1913,7 @@ write_c_file_stat (FILE *stream, const char *name ATTRIBUTE_UNUSED) } } /* q points to null at end of the string (or . of the .so version) */ - prefix = xmalloc (q - p + 1); + prefix = XNEWVEC (char, q - p + 1); strncpy (prefix, p, q - p); prefix[q - p] = 0; for (r = prefix; *r; r++) @@ -1948,14 +2074,12 @@ write_c_file_glob (FILE *stream, const char *name ATTRIBUTE_UNUSED) static void write_c_file (FILE *stream, const char *name) { - fprintf (stream, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n"); #ifndef LD_INIT_SWITCH if (! shared_obj) write_c_file_glob (stream, name); else #endif write_c_file_stat (stream, name); - fprintf (stream, "#ifdef __cplusplus\n}\n#endif\n"); } #ifdef COLLECT_EXPORT_LIST @@ -1985,11 +2109,15 @@ static void scan_prog_file (const char *prog_name, enum pass which_pass) { void (*int_handler) (int); +#ifdef SIGQUIT void (*quit_handler) (int); +#endif char *real_nm_argv[4]; - const char **nm_argv = (const char **) real_nm_argv; + const char **nm_argv = CONST_CAST2 (const char **, char**, real_nm_argv); int argc = 0; - int pipe_fd[2]; + struct pex_obj *pex; + const char *errmsg; + int err; char *p, buf[1024]; FILE *inf; @@ -1998,7 +2126,7 @@ scan_prog_file (const char *prog_name, enum pass which_pass) /* If we do not have an `nm', complain. */ if (nm_file_name == 0) - fatal ("cannot find `nm'"); + fatal ("cannot find 'nm'"); nm_argv[argc++] = nm_file_name; if (NM_FLAGS[0] != '\0') @@ -2007,13 +2135,6 @@ scan_prog_file (const char *prog_name, enum pass which_pass) nm_argv[argc++] = prog_name; nm_argv[argc++] = (char *) 0; - if (pipe (pipe_fd) < 0) - fatal_perror ("pipe"); - - inf = fdopen (pipe_fd[0], "r"); - if (inf == (FILE *) 0) - fatal_perror ("fdopen"); - /* Trace if needed. */ if (vflag) { @@ -2029,35 +2150,30 @@ scan_prog_file (const char *prog_name, enum pass which_pass) fflush (stdout); fflush (stderr); - /* Spawn child nm on pipe. */ - pid = vfork (); - if (pid == -1) - fatal_perror (VFORK_STRING); + pex = pex_init (PEX_USE_PIPES, "collect2", NULL); + if (pex == NULL) + fatal_perror ("pex_init failed"); - if (pid == 0) /* child context */ + errmsg = pex_run (pex, 0, nm_file_name, real_nm_argv, NULL, NULL, &err); + if (errmsg != NULL) { - /* setup stdout */ - if (dup2 (pipe_fd[1], 1) < 0) - fatal_perror ("dup2 %d 1", pipe_fd[1]); - - if (close (pipe_fd[0]) < 0) - fatal_perror ("close %d", pipe_fd[0]); - - if (close (pipe_fd[1]) < 0) - fatal_perror ("close %d", pipe_fd[1]); - - execv (nm_file_name, real_nm_argv); - fatal_perror ("execv %s", nm_file_name); + if (err != 0) + { + errno = err; + fatal_perror (errmsg); + } + else + fatal (errmsg); } - /* Parent context from here on. */ int_handler = (void (*) (int)) signal (SIGINT, SIG_IGN); #ifdef SIGQUIT quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN); #endif - if (close (pipe_fd[1]) < 0) - fatal_perror ("close %d", pipe_fd[1]); + inf = pex_read_output (pex, 0); + if (inf == NULL) + fatal_perror ("can't open nm output"); if (debug) fprintf (stderr, "\nnm output with constructors/destructors.\n"); @@ -2089,17 +2205,17 @@ scan_prog_file (const char *prog_name, enum pass which_pass) *end = '\0'; switch (is_ctor_dtor (name)) { - case 1: + case SYM_CTOR: if (which_pass != PASS_LIB) add_to_list (&constructors, name); break; - case 2: + case SYM_DTOR: if (which_pass != PASS_LIB) add_to_list (&destructors, name); break; - case 3: + case SYM_INIT: if (which_pass != PASS_LIB) fatal ("init function found in object %s", prog_name); #ifndef LD_INIT_SWITCH @@ -2107,7 +2223,7 @@ scan_prog_file (const char *prog_name, enum pass which_pass) #endif break; - case 4: + case SYM_FINI: if (which_pass != PASS_LIB) fatal ("fini function found in object %s", prog_name); #ifndef LD_FINI_SWITCH @@ -2115,7 +2231,7 @@ scan_prog_file (const char *prog_name, enum pass which_pass) #endif break; - case 5: + case SYM_DWEH: if (which_pass != PASS_LIB) add_to_list (&frame_tables, name); break; @@ -2131,10 +2247,7 @@ scan_prog_file (const char *prog_name, enum pass which_pass) if (debug) fprintf (stderr, "\n"); - if (fclose (inf) != 0) - fatal_perror ("fclose"); - - do_wait (nm_file_name); + do_wait (nm_file_name, pex); signal (SIGINT, int_handler); #ifdef SIGQUIT @@ -2142,269 +2255,6 @@ scan_prog_file (const char *prog_name, enum pass which_pass) #endif } -#if SUNOS4_SHARED_LIBRARIES - -/* Routines to scan the SunOS 4 _DYNAMIC structure to find shared libraries - that the output file depends upon and their initialization/finalization - routines, if any. */ - -#include -#include -#include -#include -#include -#include -#include - -/* pointers to the object file */ -unsigned object; /* address of memory mapped file */ -unsigned objsize; /* size of memory mapped to file */ -char * code; /* pointer to code segment */ -char * data; /* pointer to data segment */ -struct nlist *symtab; /* pointer to symbol table */ -struct link_dynamic *ld; -struct link_dynamic_2 *ld_2; -struct head libraries; - -/* Map the file indicated by NAME into memory and store its address. */ - -static void -mapfile (const char *name) -{ - int fp; - struct stat s; - if ((fp = open (name, O_RDONLY)) == -1) - fatal ("unable to open file '%s'", name); - if (fstat (fp, &s) == -1) - fatal ("unable to stat file '%s'", name); - - objsize = s.st_size; - object = (unsigned) mmap (0, objsize, PROT_READ|PROT_WRITE, MAP_PRIVATE, - fp, 0); - if (object == (unsigned)-1) - fatal ("unable to mmap file '%s'", name); - - close (fp); -} - -/* Helpers for locatelib. */ - -static const char *libname; - -static int -libselect (struct direct *d) -{ - return (strncmp (libname, d->d_name, strlen (libname)) == 0); -} - -/* If one file has an additional numeric extension past LIBNAME, then put - that one first in the sort. If both files have additional numeric - extensions, then put the one with the higher number first in the sort. - - We must verify that the extension is numeric, because Sun saves the - original versions of patched libraries with a .FCS extension. Files with - invalid extensions must go last in the sort, so that they will not be used. */ - -static int -libcompare (struct direct **d1, struct direct **d2) -{ - int i1, i2 = strlen (libname); - char *e1 = (*d1)->d_name + i2; - char *e2 = (*d2)->d_name + i2; - - while (*e1 && *e2 && *e1 == '.' && *e2 == '.' - && e1[1] && ISDIGIT (e1[1]) && e2[1] && ISDIGIT (e2[1])) - { - ++e1; - ++e2; - i1 = strtol (e1, &e1, 10); - i2 = strtol (e2, &e2, 10); - if (i1 != i2) - return i1 - i2; - } - - if (*e1) - { - /* It has a valid numeric extension, prefer this one. */ - if (*e1 == '.' && e1[1] && ISDIGIT (e1[1])) - return 1; - /* It has an invalid numeric extension, must prefer the other one. */ - else - return -1; - } - else if (*e2) - { - /* It has a valid numeric extension, prefer this one. */ - if (*e2 == '.' && e2[1] && ISDIGIT (e2[1])) - return -1; - /* It has an invalid numeric extension, must prefer the other one. */ - else - return 1; - } - else - return 0; -} - -/* Given the name NAME of a dynamic dependency, find its pathname and add - it to the list of libraries. */ - -static void -locatelib (const char *name) -{ - static const char **l; - static int cnt; - char buf[MAXPATHLEN]; - char *p, *q; - const char **pp; - - if (l == 0) - { - char *ld_rules; - char *ldr = 0; - /* counting elements in array, need 1 extra for null */ - cnt = 1; - ld_rules = (char *) (ld_2->ld_rules + code); - if (ld_rules) - { - cnt++; - for (; *ld_rules != 0; ld_rules++) - if (*ld_rules == ':') - cnt++; - ld_rules = (char *) (ld_2->ld_rules + code); - ldr = xstrdup (ld_rules); - } - p = getenv ("LD_LIBRARY_PATH"); - q = 0; - if (p) - { - cnt++; - for (q = p ; *q != 0; q++) - if (*q == ':') - cnt++; - q = xstrdup (p); - } - l = xmalloc ((cnt + 3) * sizeof (char *)); - pp = l; - if (ldr) - { - *pp++ = ldr; - for (; *ldr != 0; ldr++) - if (*ldr == ':') - { - *ldr++ = 0; - *pp++ = ldr; - } - } - if (q) - { - *pp++ = q; - for (; *q != 0; q++) - if (*q == ':') - { - *q++ = 0; - *pp++ = q; - } - } - /* built in directories are /lib, /usr/lib, and /usr/local/lib */ - *pp++ = "/lib"; - *pp++ = "/usr/lib"; - *pp++ = "/usr/local/lib"; - *pp = 0; - } - libname = name; - for (pp = l; *pp != 0 ; pp++) - { - struct direct **namelist; - int entries; - if ((entries = scandir (*pp, &namelist, libselect, libcompare)) > 0) - { - sprintf (buf, "%s/%s", *pp, namelist[entries - 1]->d_name); - add_to_list (&libraries, buf); - if (debug) - fprintf (stderr, "%s\n", buf); - break; - } - } - if (*pp == 0) - { - if (debug) - notice ("not found\n"); - else - fatal ("dynamic dependency %s not found", name); - } -} - -/* Scan the _DYNAMIC structure of the output file to find shared libraries - that it depends upon and any constructors or destructors they contain. */ - -static void -scan_libraries (const char *prog_name) -{ - struct exec *header; - char *base; - struct link_object *lo; - char buff[MAXPATHLEN]; - struct id *list; - - mapfile (prog_name); - header = (struct exec *)object; - if (N_BADMAG (*header)) - fatal ("bad magic number in file '%s'", prog_name); - if (header->a_dynamic == 0) - return; - - code = (char *) (N_TXTOFF (*header) + (long) header); - data = (char *) (N_DATOFF (*header) + (long) header); - symtab = (struct nlist *) (N_SYMOFF (*header) + (long) header); - - if (header->a_magic == ZMAGIC && header->a_entry == 0x20) - { - /* shared object */ - ld = (struct link_dynamic *) (symtab->n_value + code); - base = code; - } - else - { - /* executable */ - ld = (struct link_dynamic *) data; - base = code-PAGSIZ; - } - - if (debug) - notice ("dynamic dependencies.\n"); - - ld_2 = (struct link_dynamic_2 *) ((long) ld->ld_un.ld_2 + (long)base); - for (lo = (struct link_object *) ld_2->ld_need; lo; - lo = (struct link_object *) lo->lo_next) - { - char *name; - lo = (struct link_object *) ((long) lo + code); - name = (char *) (code + lo->lo_name); - if (lo->lo_library) - { - if (debug) - fprintf (stderr, "\t-l%s.%d => ", name, lo->lo_major); - sprintf (buff, "lib%s.so.%d.%d", name, lo->lo_major, lo->lo_minor); - locatelib (buff); - } - else - { - if (debug) - fprintf (stderr, "\t%s\n", name); - add_to_list (&libraries, name); - } - } - - if (debug) - fprintf (stderr, "\n"); - - /* now iterate through the library list adding their symbols to - the list. */ - for (list = libraries.first; list; list = list->next) - scan_prog_file (list->name, PASS_LIB); -} - -#else /* SUNOS4_SHARED_LIBRARIES */ #ifdef LDD_SUFFIX /* Use the List Dynamic Dependencies program to find shared libraries that @@ -2417,18 +2267,22 @@ scan_libraries (const char *prog_name) static struct head libraries; /* list of shared libraries found */ struct id *list; void (*int_handler) (int); +#ifdef SIGQUIT void (*quit_handler) (int); +#endif char *real_ldd_argv[4]; - const char **ldd_argv = (const char **) real_ldd_argv; + const char **ldd_argv = CONST_CAST2 (const char **, char **, real_ldd_argv); int argc = 0; - int pipe_fd[2]; + struct pex_obj *pex; + const char *errmsg; + int err; char buf[1024]; FILE *inf; /* If we do not have an `ldd', complain. */ if (ldd_file_name == 0) { - error ("cannot find `ldd'"); + error ("cannot find 'ldd'"); return; } @@ -2436,13 +2290,6 @@ scan_libraries (const char *prog_name) ldd_argv[argc++] = prog_name; ldd_argv[argc++] = (char *) 0; - if (pipe (pipe_fd) < 0) - fatal_perror ("pipe"); - - inf = fdopen (pipe_fd[0], "r"); - if (inf == (FILE *) 0) - fatal_perror ("fdopen"); - /* Trace if needed. */ if (vflag) { @@ -2458,35 +2305,30 @@ scan_libraries (const char *prog_name) fflush (stdout); fflush (stderr); - /* Spawn child ldd on pipe. */ - pid = vfork (); - if (pid == -1) - fatal_perror (VFORK_STRING); + pex = pex_init (PEX_USE_PIPES, "collect2", NULL); + if (pex == NULL) + fatal_perror ("pex_init failed"); - if (pid == 0) /* child context */ + errmsg = pex_run (pex, 0, ldd_file_name, real_ldd_argv, NULL, NULL, &err); + if (errmsg != NULL) { - /* setup stdout */ - if (dup2 (pipe_fd[1], 1) < 0) - fatal_perror ("dup2 %d 1", pipe_fd[1]); - - if (close (pipe_fd[0]) < 0) - fatal_perror ("close %d", pipe_fd[0]); - - if (close (pipe_fd[1]) < 0) - fatal_perror ("close %d", pipe_fd[1]); - - execv (ldd_file_name, real_ldd_argv); - fatal_perror ("execv %s", ldd_file_name); + if (err != 0) + { + errno = err; + fatal_perror (errmsg); + } + else + fatal (errmsg); } - /* Parent context from here on. */ - int_handler = (void (*) (int))) signal (SIGINT, SIG_IGN; + int_handler = (void (*) (int)) signal (SIGINT, SIG_IGN); #ifdef SIGQUIT - quit_handler = (void (*) (int))) signal (SIGQUIT, SIG_IGN; + quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN); #endif - if (close (pipe_fd[1]) < 0) - fatal_perror ("close %d", pipe_fd[1]); + inf = pex_read_output (pex, 0); + if (inf == NULL) + fatal_perror ("can't open ldd output"); if (debug) notice ("\nldd output with constructors/destructors.\n"); @@ -2514,7 +2356,7 @@ scan_libraries (const char *prog_name) *end = '\0'; if (access (name, R_OK) == 0) - add_to_list (&libraries, name); + add_to_list (&libraries, name); else fatal ("unable to open dynamic dependency '%s'", buf); @@ -2524,24 +2366,20 @@ scan_libraries (const char *prog_name) if (debug) fprintf (stderr, "\n"); - if (fclose (inf) != 0) - fatal_perror ("fclose"); - - do_wait (ldd_file_name); + do_wait (ldd_file_name, pex); signal (SIGINT, int_handler); #ifdef SIGQUIT signal (SIGQUIT, quit_handler); #endif - /* now iterate through the library list adding their symbols to + /* Now iterate through the library list adding their symbols to the list. */ for (list = libraries.first; list; list = list->next) scan_prog_file (list->name, PASS_LIB); } #endif /* LDD_SUFFIX */ -#endif /* SUNOS4_SHARED_LIBRARIES */ #endif /* OBJECT_FORMAT_NONE */ @@ -2552,7 +2390,7 @@ scan_libraries (const char *prog_name) #ifdef OBJECT_FORMAT_COFF -#if defined(EXTENDED_COFF) +#if defined (EXTENDED_COFF) # define GCC_SYMBOLS(X) (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax) # define GCC_SYMENT SYMR @@ -2565,19 +2403,31 @@ scan_libraries (const char *prog_name) # define GCC_SYMBOLS(X) (HEADER(ldptr).f_nsyms) # define GCC_SYMENT SYMENT -# define GCC_OK_SYMBOL(X) \ - (((X).n_sclass == C_EXT) && \ - ((X).n_scnum > N_UNDEF) && \ - (aix64_flag \ - || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \ - || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT)))) -# define GCC_UNDEF_SYMBOL(X) \ - (((X).n_sclass == C_EXT) && ((X).n_scnum == N_UNDEF)) +# if defined (C_WEAKEXT) +# define GCC_OK_SYMBOL(X) \ + (((X).n_sclass == C_EXT || (X).n_sclass == C_WEAKEXT) && \ + ((X).n_scnum > N_UNDEF) && \ + (aix64_flag \ + || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \ + || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT)))) +# define GCC_UNDEF_SYMBOL(X) \ + (((X).n_sclass == C_EXT || (X).n_sclass == C_WEAKEXT) && \ + ((X).n_scnum == N_UNDEF)) +# else +# define GCC_OK_SYMBOL(X) \ + (((X).n_sclass == C_EXT) && \ + ((X).n_scnum > N_UNDEF) && \ + (aix64_flag \ + || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \ + || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT)))) +# define GCC_UNDEF_SYMBOL(X) \ + (((X).n_sclass == C_EXT) && ((X).n_scnum == N_UNDEF)) +# endif # define GCC_SYMINC(X) ((X).n_numaux+1) # define GCC_SYMZERO(X) 0 /* 0757 = U803XTOCMAGIC (AIX 4.3) and 0767 = U64_TOCMAGIC (AIX V5) */ -#ifdef _AIX51 +#if TARGET_AIX_VERSION >= 51 # define GCC_CHECK_HDR(X) \ ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \ || (HEADER (X).f_magic == 0767 && aix64_flag)) @@ -2616,9 +2466,19 @@ static int ignore_library (const char *); static int ignore_library (const char *name) { - const char *const *p = &aix_std_libs[0]; - while (*p++ != NULL) - if (! strcmp (name, *p)) return 1; + const char *const *p; + size_t length; + + if (target_system_root[0] != '\0') + { + length = strlen (target_system_root); + if (strncmp (name, target_system_root, length) != 0) + return 0; + name += length; + } + for (p = &aix_std_libs[0]; *p != NULL; ++p) + if (strcmp (name, *p) == 0) + return 1; return 0; } #endif /* COLLECT_EXPORT_LIST */ @@ -2658,10 +2518,10 @@ scan_prog_file (const char *prog_name, enum pass which_pass) { #endif /* Some platforms (e.g. OSF4) declare ldopen as taking a - non-const char * filename parameter, even though it will not - modify that string. So we must cast away const-ness here, - which will cause -Wcast-qual to burp. */ - if ((ldptr = ldopen ((char *)prog_name, ldptr)) != NULL) + non-const char * filename parameter, even though it will not + modify that string. So we must cast away const-ness here, + using CONST_CAST to prevent complaints from -Wcast-qual. */ + if ((ldptr = ldopen (CONST_CAST (char *, prog_name), ldptr)) != NULL) { if (! MY_ISCOFF (HEADER (ldptr).f_magic)) fatal ("%s: not a COFF file", prog_name); @@ -2689,7 +2549,7 @@ scan_prog_file (const char *prog_name, enum pass which_pass) char *name; if ((name = ldgetname (ldptr, &symbol)) == NULL) - continue; /* should never happen */ + continue; /* Should never happen. */ #ifdef XCOFF_DEBUGGING_INFO /* All AIX function names have a duplicate entry @@ -2700,33 +2560,33 @@ scan_prog_file (const char *prog_name, enum pass which_pass) switch (is_ctor_dtor (name)) { - case 1: + case SYM_CTOR: if (! is_shared) add_to_list (&constructors, name); -#ifdef COLLECT_EXPORT_LIST +#if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH) if (which_pass == PASS_OBJ) add_to_list (&exports, name); #endif break; - case 2: + case SYM_DTOR: if (! is_shared) add_to_list (&destructors, name); -#ifdef COLLECT_EXPORT_LIST +#if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH) if (which_pass == PASS_OBJ) add_to_list (&exports, name); #endif break; #ifdef COLLECT_EXPORT_LIST - case 3: + case SYM_INIT: #ifndef LD_INIT_SWITCH if (is_shared) add_to_list (&constructors, name); #endif break; - case 4: + case SYM_FINI: #ifndef LD_INIT_SWITCH if (is_shared) add_to_list (&destructors, name); @@ -2734,10 +2594,10 @@ scan_prog_file (const char *prog_name, enum pass which_pass) break; #endif - case 5: + case SYM_DWEH: if (! is_shared) add_to_list (&frame_tables, name); -#ifdef COLLECT_EXPORT_LIST +#if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH) if (which_pass == PASS_OBJ) add_to_list (&exports, name); #endif @@ -2745,13 +2605,14 @@ scan_prog_file (const char *prog_name, enum pass which_pass) default: /* not a constructor or destructor */ #ifdef COLLECT_EXPORT_LIST - /* If we are building a shared object on AIX we need - to explicitly export all global symbols. */ - if (shared_obj) - { - if (which_pass == PASS_OBJ && (! export_flag)) - add_to_list (&exports, name); - } + /* Explicitly export all global symbols when + building a shared object on AIX, but do not + re-export symbols from another shared object + and do not export symbols if the user + provides an explicit export list. */ + if (shared_obj && !is_shared + && which_pass == PASS_OBJ && !export_flag) + add_to_list (&exports, name); #endif continue; } @@ -2804,12 +2665,14 @@ resolve_lib_name (const char *name) { char *lib_buf; int i, j, l = 0; + /* Library extensions for AIX dynamic linking. */ + const char * const libexts[2] = {"a", "so"}; for (i = 0; libpaths[i]; i++) if (libpaths[i]->max_len > l) l = libpaths[i]->max_len; - lib_buf = xmalloc (l + strlen(name) + 10); + lib_buf = XNEWVEC (char, l + strlen(name) + 10); for (i = 0; libpaths[i]; i++) { @@ -2822,14 +2685,15 @@ resolve_lib_name (const char *name) const char *p = ""; if (list->prefix[strlen(list->prefix)-1] != '/') p = "/"; - for (j = 0; libexts[j]; j++) + for (j = 0; j < 2; j++) { sprintf (lib_buf, "%s%slib%s.%s", - list->prefix, p, name, libexts[j]); -if (debug) fprintf (stderr, "searching for: %s\n", lib_buf); + list->prefix, p, name, + libexts[(j + aixrtl_flag) % 2]); + if (debug) fprintf (stderr, "searching for: %s\n", lib_buf); if (file_exists (lib_buf)) { -if (debug) fprintf (stderr, "found: %s\n", lib_buf); + if (debug) fprintf (stderr, "found: %s\n", lib_buf); return (lib_buf); } }