/* 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, 2004, 2005 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007 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).
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
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
+<http://www.gnu.org/licenses/>. */
/* Build tables of static constructors and destructors and run ld. */
the utilities are not correct for a cross-compiler; we have to hope that
cross-versions are in the proper directories. */
-#ifdef CROSS_COMPILE
+#ifdef CROSS_DIRECTORY_STRUCTURE
#undef OBJECT_FORMAT_COFF
#undef MD_EXEC_PREFIX
#undef REAL_LD_FILE_NAME
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 debug; /* true if -debug */
-static int shared_obj; /* true if -shared */
+static int shared_obj; /* true if -shared */
static const char *c_file; /* <xxx>.c for constructor/destructor list. */
static const char *o_file; /* <xxx>.o for constructor/destructor list. */
#ifdef COLLECT_EXPORT_LIST
-static const char *export_file; /* <xxx>.x for AIX export list. */
+static const char *export_file; /* <xxx>.x for AIX export list. */
#endif
const char *ldout; /* File for ld stdout. */
const char *lderrout; /* File for ld stderr. */
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 */
#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;
#endif
static char *extract_string (const char **);
\f
-#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 */
-\f
/* Delete tempfiles and exit function. */
void
if (status != 0 && output_file != 0 && output_file[0])
maybe_unlink (output_file);
+ if (response_file)
+ maybe_unlink (response_file);
+
exit (status);
}
\f
/* 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);
/* 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);
/* 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);
}
maybe_unlink (export_file);
#endif
+ if (response_file)
+ maybe_unlink (response_file);
+
signal (signo, SIG_DFL);
raise (signo);
}
obstack_1grow (&temporary_obstack, '\0');
*pp = p;
- return obstack_finish (&temporary_obstack);
+ return XOBFINISH (&temporary_obstack, char *);
}
\f
void
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 ('.', to);
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. */
len += strlen (HOST_EXECUTABLE_SUFFIX);
#endif
- temp = xmalloc (len);
+ temp = XNEWVEC (char, len);
/* Determine the filename to execute (special case for absolute paths). */
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)
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);
else
endp++;
}
+ free (nstore);
}
\f
/* Main program. */
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
#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;
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");
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";
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')
ld2--;
}
if (!strcmp (arg, "-dynamic-linker") && argv[1])
- {
+ {
++argv;
*ld1++ = *ld2++ = *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. */
else
{
/* Saving a full library name. */
- add_to_list (&libs, arg);
- }
+ add_to_list (&libs, arg);
+ }
#endif
}
}
/* Strip now if it was requested on the command line. */
if (strip_flag)
{
- char **real_strip_argv = xcalloc (sizeof (char *), 3);
+ char **real_strip_argv = XCNEWVEC (char *, 3);
const char ** strip_argv = (const char **) real_strip_argv;
strip_argv[0] = strip_file_name;
error ("%s returned %d exit status", prog, ret);
collect_exit (ret);
}
+
+ if (response_file)
+ {
+ unlink (response_file);
+ response_file = NULL;
+ }
}
\f
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)
{
fatal (errmsg);
}
+ if (response_arg)
+ free (response_arg);
+
return pex;
}
|| 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;
}
}
/* 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++)
*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);
# 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))))
+ ((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))
+ ((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))))
+ ((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
{
#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. */
+ 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)
{
if (! MY_ISCOFF (HEADER (ldptr).f_magic))