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);
}
}