OSDN Git Service

* reorg.c (mostly_true_jump): Clean up code depending on
[pf3gnuchains/gcc-fork.git] / gcc / collect2.c
index a8eaf11..f4cc46a 100644 (file)
@@ -1,7 +1,7 @@
 /* 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 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005 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).
@@ -20,8 +20,8 @@ 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.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 
 /* 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 <vfork.h>
-#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
@@ -185,6 +172,7 @@ 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 */
@@ -196,7 +184,8 @@ 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.  */
 #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
@@ -216,9 +205,6 @@ static struct head frame_tables;    /* list of frame unwind info tables */
 struct obstack temporary_obstack;
 char * temporary_firstobj;
 
-/* Holds the return value of pexecute and fork.  */
-int pid;
-
 /* Structure to hold all the directories in which to search for files to
    execute.  */
 
@@ -242,7 +228,6 @@ 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
 
 static void handler (int);
@@ -251,7 +236,7 @@ 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 *);
@@ -286,26 +271,6 @@ static char *resolve_lib_name (const char *);
 #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
@@ -324,10 +289,16 @@ 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);
 
@@ -337,26 +308,26 @@ collect_exit (int 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);
 
@@ -366,13 +337,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);
 
@@ -382,13 +353,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);
 }
@@ -414,13 +385,16 @@ 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
 
   signal (signo, SIG_DFL);
-  kill (getpid (), signo);
+  raise (signo);
 }
 
 \f
@@ -459,11 +433,11 @@ extract_string (const char **pp)
 
   obstack_1grow (&temporary_obstack, '\0');
   *pp = p;
-  return obstack_finish (&temporary_obstack);
+  return XOBFINISH (&temporary_obstack, char *);
 }
 \f
 void
-dump_file (const char *name)
+dump_file (const char *name, FILE *to)
 {
   FILE *stream = fopen (name, "r");
 
@@ -480,10 +454,10 @@ 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);
@@ -500,25 +474,25 @@ dump_file (const char *name)
          if (result)
            {
              int diff;
-             fputs (result, stderr);
+             fputs (result, to);
 
              diff = strlen (word) - strlen (result);
              while (diff > 0 && c == ' ')
-               --diff, putc (' ', stderr);
+               --diff, putc (' ', to);
              while (diff < 0 && c == ' ')
                ++diff, c = getc (stream);
 
              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);
 }
@@ -837,6 +811,9 @@ 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
@@ -1006,6 +983,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";
@@ -1087,6 +1065,8 @@ main (int argc, char **argv)
                 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
 
@@ -1097,6 +1077,11 @@ main (int argc, char **argv)
                  ld1--;
                  ld2--;
                }
+             if (!strcmp (arg, "-dynamic-linker") && argv[1])
+               {
+                 ++argv;
+                 *ld1++ = *ld2++ = *argv;
+               }
              break;
 
            case 'l':
@@ -1494,11 +1479,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))
@@ -1517,9 +1505,9 @@ 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);
@@ -1530,14 +1518,13 @@ do_wait (const char *prog)
 \f
 /* 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;
 
   if (vflag || debug)
     {
@@ -1562,49 +1549,35 @@ 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);
-
-  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);
-    }
+    fatal ("cannot find '%s'", prog);
 
-  pid = pexecute (argv[0], argv, argv[0], NULL, &errmsg_fmt, &errmsg_arg,
-                 (PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH));
+  pex = pex_init (0, "collect2", NULL);
+  if (pex == NULL)
+    fatal_perror ("pex_init failed");
 
-  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);
+  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);
 }
 \f
 /* Unlink a file unless we are debugging.  */
@@ -1613,7 +1586,7 @@ static void
 maybe_unlink (const char *file)
 {
   if (!debug)
-    unlink (file);
+    unlink_if_ordinary (file);
   else
     notice ("[Leaving %s]\n", file);
 }
@@ -2026,11 +1999,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;
   int argc = 0;
-  int pipe_fd[2];
+  struct pex_obj *pex;
+  const char *errmsg;
+  int err;
   char *p, buf[1024];
   FILE *inf;
 
@@ -2039,7 +2016,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')
@@ -2048,13 +2025,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)
     {
@@ -2070,35 +2040,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");
@@ -2172,10 +2137,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
@@ -2195,18 +2157,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;
   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;
     }
 
@@ -2214,13 +2180,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)
     {
@@ -2236,35 +2195,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);
 #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 ldd output");
 
   if (debug)
     notice ("\nldd output with constructors/destructors.\n");
@@ -2302,10 +2256,7 @@ 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
@@ -2594,6 +2545,8 @@ 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)
@@ -2612,14 +2565,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);
                }
            }