i386.c (legitimize_tls_address): Generate tls_initial_exec_64_sun only when !TARGET_X32.
[gcc.git] / gcc / collect2.c
index 0c554f0534670c58955296e816611cd67e7e7e49..9ee12c7a50267c643450a554b7d044886cf91cc4 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, 2005, 2007, 2008, 2009, 2010, 2011
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011, 2012
    Free Software Foundation, Inc.
    Contributed by Chris Smith (csmith@convex.com).
    Heavily modified by Michael Meissner (meissner@cygnus.com),
@@ -44,6 +44,7 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "collect2.h"
 #include "collect2-aix.h"
+#include "diagnostic.h"
 #include "demangle.h"
 #include "obstack.h"
 #include "intl.h"
@@ -178,7 +179,6 @@ struct head
 bool vflag;                            /* true if -v or --version */ 
 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 */
@@ -237,6 +237,12 @@ static const char *target_system_root = TARGET_SYSTEM_ROOT;
 static const char *target_system_root = "";
 #endif
 
+/* Whether we may unlink the output file, which should be set as soon as we
+   know we have successfully produced it.  This is typically useful to prevent
+   blindly attempting to unlink a read-only output that the target linker
+   would leave untouched.  */
+bool may_unlink_output_file = false;
+
 /* Structure to hold all the directories in which to search for files to
    execute.  */
 
@@ -323,9 +329,6 @@ static void write_c_file_glob (FILE *, const char *);
 #ifdef SCAN_LIBRARIES
 static void scan_libraries (const char *);
 #endif
-#if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
-static int is_in_args (const char *, const char **, const char **);
-#endif
 #ifdef COLLECT_EXPORT_LIST
 #if 0
 static int is_in_list (const char *, struct id *);
@@ -444,62 +447,6 @@ notice_translated (const char *cmsgid, ...)
   vfprintf (stderr, cmsgid, ap);
   va_end (ap);
 }
-
-/* Die when sys call fails.  */
-
-void
-fatal_perror (const char * cmsgid, ...)
-{
-  int e = errno;
-  va_list ap;
-
-  va_start (ap, cmsgid);
-  fprintf (stderr, "collect2: ");
-  vfprintf (stderr, _(cmsgid), ap);
-  fprintf (stderr, ": %s\n", xstrerror (e));
-  va_end (ap);
-
-  collect_exit (FATAL_EXIT_CODE);
-}
-
-/* Just die.  */
-
-void
-fatal (const char * cmsgid, ...)
-{
-  va_list ap;
-
-  va_start (ap, cmsgid);
-  fprintf (stderr, "collect2: ");
-  vfprintf (stderr, _(cmsgid), ap);
-  fprintf (stderr, "\n");
-  va_end (ap);
-
-  collect_exit (FATAL_EXIT_CODE);
-}
-
-/* Write error message.  */
-
-void
-error (const char * gmsgid, ...)
-{
-  va_list ap;
-
-  va_start (ap, gmsgid);
-  fprintf (stderr, "collect2: ");
-  vfprintf (stderr, _(gmsgid), ap);
-  fprintf (stderr, "\n");
-  va_end(ap);
-}
-
-/* In case obstack is linked in, and abort is defined to fancy_abort,
-   provide a default entry.  */
-
-void
-fancy_abort (const char *file, int line, const char *func)
-{
-  fatal ("internal gcc abort in %s, at %s:%d", func, file, line);
-}
 \f
 static void
 handler (int signo)
@@ -895,7 +842,7 @@ add_lto_object (struct lto_object_list *list, const char *name)
    files contain LTO info.  The linker command line LTO_LD_ARGV
    represents the linker command that would produce a final executable
    without the use of LTO. OBJECT_LST is a vector of object file names
-   appearing in LTO_LD_ARGV that are to be considerd for link-time
+   appearing in LTO_LD_ARGV that are to be considered for link-time
    recompilation, where OBJECT is a pointer to the last valid element.
    (This awkward convention avoids an impedance mismatch with the
    usage of similarly-named variables in main().)  The elements of
@@ -953,7 +900,7 @@ maybe_run_lto_and_relink (char **lto_ld_argv, char **object_lst,
       size_t num_files;
 
       if (!lto_wrapper)
-       fatal ("COLLECT_LTO_WRAPPER must be set");
+       fatal_error ("COLLECT_LTO_WRAPPER must be set");
 
       num_lto_c_args++;
 
@@ -1077,7 +1024,7 @@ int
 main (int argc, char **argv)
 {
   static const char *const ld_suffix   = "ld";
-  static const char *const plugin_ld_suffix = PLUGIN_LD;
+  static const char *const plugin_ld_suffix = PLUGIN_LD_SUFFIX;
   static const char *const real_ld_suffix = "real-ld";
   static const char *const collect_ld_suffix = "collect-ld";
   static const char *const nm_suffix   = "nm";
@@ -1147,10 +1094,20 @@ main (int argc, char **argv)
   const char **ld2;
   char **object_lst;
   const char **object;
+#ifdef TARGET_AIX_VERSION
+  int object_nbr = argc;
+#endif
   int first_file;
   int num_c_args;
   char **old_argv;
 
+  p = argv[0] + strlen (argv[0]);
+  while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
+    --p;
+  progname = p;
+
+  xmalloc_set_program_name (progname);
+
   old_argv = argv;
   expandargv (&argc, &argv);
   if (argv != old_argv)
@@ -1160,10 +1117,12 @@ main (int argc, char **argv)
 
   num_c_args = argc + 9;
 
+#ifndef HAVE_LD_DEMANGLE
   no_demangle = !! getenv ("COLLECT_NO_DEMANGLE");
 
   /* Suppress demangling by the real linker, which may be broken.  */
-  putenv (xstrdup ("COLLECT_NO_DEMANGLE="));
+  putenv (xstrdup ("COLLECT_NO_DEMANGLE=1"));
+#endif
 
 #if defined (COLLECT2_HOST_INITIALIZATION)
   /* Perform system dependent initialization, if necessary.  */
@@ -1181,6 +1140,8 @@ main (int argc, char **argv)
 
   gcc_init_libintl ();
 
+  diagnostic_initialize (global_dc, 0);
+
   /* Do not invoke xcalloc before this point, since locale needs to be
      set first, in case a diagnostic is issued.  */
 
@@ -1270,7 +1231,7 @@ main (int argc, char **argv)
   c_ptr = CONST_CAST2 (const char **, char **, c_argv);
 
   if (argc < 2)
-    fatal ("no arguments");
+    fatal_error ("no arguments");
 
 #ifdef SIGQUIT
   if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
@@ -1451,12 +1412,6 @@ 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;
@@ -1491,6 +1446,60 @@ main (int argc, char **argv)
                         "configuration");
 #endif
                }
+#ifdef TARGET_AIX_VERSION
+             else
+               {
+                 /* File containing a list of input files to process.  */
+
+                 FILE *stream;
+                  char buf[MAXPATHLEN + 2];
+                 /* Number of additionnal object files.  */
+                 int add_nbr = 0;
+                 /* Maximum of additionnal object files before vector
+                    expansion.  */
+                 int add_max = 0;
+                 const char *list_filename = arg + 2;
+
+                 /* Accept -fFILENAME and -f FILENAME.  */
+                 if (*list_filename == '\0' && argv[1])
+                   {
+                     ++argv;
+                     list_filename = *argv;
+                     *ld1++ = *ld2++ = *argv;
+                   }
+
+                 stream = fopen (list_filename, "r");
+                 if (stream == NULL)
+                   fatal_error ("can't open %s: %m", list_filename);
+
+                 while (fgets (buf, sizeof buf, stream) != NULL)
+                   {
+                     /* Remove end of line.  */
+                     int len = strlen (buf);
+                     if (len >= 1 && buf[len - 1] =='\n')
+                       buf[len - 1] = '\0';
+
+                     /* Put on object vector.
+                        Note: we only expanse vector here, so we must keep
+                        extra space for remaining arguments.  */
+                     if (add_nbr >= add_max)
+                       {
+                         int pos =
+                           object - CONST_CAST2 (const char **, char **,
+                                                 object_lst);
+                         add_max = (add_max == 0) ? 16 : add_max * 2;
+                         object_lst = XRESIZEVEC (char *, object_lst,
+                                                   object_nbr + add_max);
+                         object = CONST_CAST2 (const char **, char **,
+                                               object_lst) + pos;
+                         object_nbr += add_max;
+                       }
+                     *object++ = xstrdup (buf);
+                     add_nbr++;
+                   }
+                 fclose (stream);
+               }
+#endif
               break;
 
            case 'l':
@@ -1518,15 +1527,6 @@ main (int argc, char **argv)
            case 'L':
              add_prefix (&cmdline_lib_dirs, arg+2);
              break;
-#else
-#if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
-           case 'L':
-             if (is_in_args (arg,
-                             CONST_CAST2 (const char **, char **, ld1_argv),
-                             ld1 - 1))
-               --ld1;
-             break;
-#endif /* LINK_ELIMINATE_DUPLICATE_LDIRECTORIES */
 #endif
 
            case 'o':
@@ -1560,16 +1560,16 @@ main (int argc, char **argv)
            case '-':
              if (strcmp (arg, "--no-demangle") == 0)
                {
-                 demangle_flag = arg;
+#ifndef HAVE_LD_DEMANGLE
                  no_demangle = 1;
                  ld1--;
                  ld2--;
+#endif
                }
              else if (strncmp (arg, "--demangle", 10) == 0)
                {
-                 demangle_flag = arg;
-                 no_demangle = 0;
 #ifndef HAVE_LD_DEMANGLE
+                 no_demangle = 0;
                  if (arg[10] == '=')
                    {
                      enum demangling_styles style
@@ -1579,9 +1579,9 @@ main (int argc, char **argv)
                      else
                        current_demangling_style = style;
                    }
-#endif
                  ld1--;
                  ld2--;
+#endif
                }
              else if (strncmp (arg, "--sysroot=", 10) == 0)
                target_system_root = arg + 10;
@@ -1671,10 +1671,10 @@ main (int argc, char **argv)
 
       exportf = fopen (export_file, "w");
       if (exportf == (FILE *) 0)
-       fatal_perror ("fopen %s", export_file);
+       fatal_error ("fopen %s: %m", export_file);
       write_aix_file (exportf, exports.first);
       if (fclose (exportf))
-       fatal_perror ("fclose %s", export_file);
+       fatal_error ("fclose %s: %m", export_file);
     }
 #endif
 
@@ -1854,12 +1854,12 @@ main (int argc, char **argv)
   maybe_unlink(output_file);
   outf = fopen (c_file, "w");
   if (outf == (FILE *) 0)
-    fatal_perror ("fopen %s", c_file);
+    fatal_error ("fopen %s: %m", c_file);
 
   write_c_file (outf, c_file);
 
   if (fclose (outf))
-    fatal_perror ("fclose %s", c_file);
+    fatal_error ("fclose %s: %m", c_file);
 
   /* Tell the linker that we have initializer and finalizer functions.  */
 #ifdef LD_INIT_SWITCH
@@ -1889,10 +1889,10 @@ main (int argc, char **argv)
 #endif
       exportf = fopen (export_file, "w");
       if (exportf == (FILE *) 0)
-       fatal_perror ("fopen %s", export_file);
+       fatal_error ("fopen %s: %m", export_file);
       write_aix_file (exportf, exports.first);
       if (fclose (exportf))
-       fatal_perror ("fclose %s", export_file);
+       fatal_error ("fclose %s: %m", export_file);
     }
 #endif
 
@@ -1956,7 +1956,7 @@ collect_wait (const char *prog, struct pex_obj *pex)
   int status;
 
   if (!pex_get_status (pex, 1, &status))
-    fatal_perror ("can't get program status");
+    fatal_error ("can't get program status: %m");
   pex_free (pex);
 
   if (status)
@@ -2025,17 +2025,17 @@ collect_execute (const char *prog, char **argv, const char *outname,
       f = fopen (response_file, "w");
 
       if (f == NULL)
-        fatal ("could not open response file %s", response_file);
+        fatal_error ("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);
+        fatal_error ("could not write to response file %s", response_file);
 
       status = fclose (f);
 
       if (EOF == status)
-        fatal ("could not close response file %s", response_file);
+        fatal_error ("could not close response file %s", response_file);
 
       response_arg = concat ("@", response_file, NULL);
       response_argv[0] = argv0;
@@ -2068,11 +2068,11 @@ collect_execute (const char *prog, char **argv, const char *outname,
      since we might not end up needing something that we could not find.  */
 
   if (argv[0] == 0)
-    fatal ("cannot find '%s'", prog);
+    fatal_error ("cannot find '%s'", prog);
 
   pex = pex_init (0, "collect2", NULL);
   if (pex == NULL)
-    fatal_perror ("pex_init failed");
+    fatal_error ("pex_init failed: %m");
 
   errmsg = pex_run (pex, flags, argv[0], argv, outname,
                    errname, &err);
@@ -2081,10 +2081,10 @@ collect_execute (const char *prog, char **argv, const char *outname,
       if (err != 0)
        {
          errno = err;
-         fatal_perror (errmsg);
+         fatal_error ("%s: %m", _(errmsg));
        }
       else
-       fatal (errmsg);
+       fatal_error (errmsg);
     }
 
   free (response_arg);
@@ -2101,15 +2101,22 @@ fork_execute (const char *prog, char **argv)
   do_wait (prog, pex);
 }
 \f
-/* Unlink a file unless we are debugging.  */
+/* Unlink FILE unless we are debugging or this is the output_file
+   and we may not unlink it.  */
 
 static void
 maybe_unlink (const char *file)
 {
-  if (!debug)
-    unlink_if_ordinary (file);
-  else
-    notice ("[Leaving %s]\n", file);
+  if (debug)
+    {
+      notice ("[Leaving %s]\n", file);
+      return;
+    }
+
+  if (file == output_file && !may_unlink_output_file)
+    return;
+
+  unlink_if_ordinary (file);
 }
 
 /* Call maybe_unlink on the NULL-terminated list, FILE_LIST.  */
@@ -2229,22 +2236,6 @@ write_list (FILE *stream, const char *prefix, struct id *list)
     }
 }
 
-#if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
-/* Given a STRING, return nonzero if it occurs in the list in range
-   [ARGS_BEGIN,ARGS_END).  */
-
-static int
-is_in_args (const char *string, const char **args_begin,
-           const char **args_end)
-{
-  const char **args_pointer;
-  for (args_pointer = args_begin; args_pointer != args_end; ++args_pointer)
-    if (strcmp (string, *args_pointer) == 0)
-      return 1;
-  return 0;
-}
-#endif /* LINK_ELIMINATE_DUPLICATE_LDIRECTORIES */
-
 #ifdef COLLECT_EXPORT_LIST
 /* This function is really used only on AIX, but may be useful.  */
 #if 0
@@ -2576,13 +2567,13 @@ scan_prog_file (const char *prog_name, scanpass which_pass,
 
   /* LTO objects must be in a known format.  This check prevents
      us from accepting an archive containing LTO objects, which
-     gcc cannnot currently handle.  */
+     gcc cannot currently handle.  */
   if (which_pass == PASS_LTOINFO && !maybe_lto_object_file (prog_name))
     return;
 
   /* If we do not have an `nm', complain.  */
   if (nm_file_name == 0)
-    fatal ("cannot find 'nm'");
+    fatal_error ("cannot find 'nm'");
 
   nm_argv[argc++] = nm_file_name;
   if (NM_FLAGS[0] != '\0')
@@ -2608,7 +2599,7 @@ scan_prog_file (const char *prog_name, scanpass which_pass,
 
   pex = pex_init (PEX_USE_PIPES, "collect2", NULL);
   if (pex == NULL)
-    fatal_perror ("pex_init failed");
+    fatal_error ("pex_init failed: %m");
 
   errmsg = pex_run (pex, 0, nm_file_name, real_nm_argv, NULL, HOST_BIT_BUCKET,
                    &err);
@@ -2617,10 +2608,10 @@ scan_prog_file (const char *prog_name, scanpass which_pass,
       if (err != 0)
        {
          errno = err;
-         fatal_perror (errmsg);
+         fatal_error ("%s: %m", _(errmsg));
        }
       else
-       fatal (errmsg);
+       fatal_error (errmsg);
     }
 
   int_handler  = (void (*) (int)) signal (SIGINT,  SIG_IGN);
@@ -2630,7 +2621,7 @@ scan_prog_file (const char *prog_name, scanpass which_pass,
 
   inf = pex_read_output (pex, 0);
   if (inf == NULL)
-    fatal_perror ("can't open nm output");
+    fatal_error ("can't open nm output: %m");
 
   if (debug)
     {
@@ -2713,7 +2704,7 @@ scan_prog_file (const char *prog_name, scanpass which_pass,
          if (! (filter & SCAN_INIT))
            break;
          if (which_pass != PASS_LIB)
-           fatal ("init function found in object %s", prog_name);
+           fatal_error ("init function found in object %s", prog_name);
 #ifndef LD_INIT_SWITCH
          add_to_list (&constructors, name);
 #endif
@@ -2723,7 +2714,7 @@ scan_prog_file (const char *prog_name, scanpass which_pass,
          if (! (filter & SCAN_FINI))
            break;
          if (which_pass != PASS_LIB)
-           fatal ("fini function found in object %s", prog_name);
+           fatal_error ("fini function found in object %s", prog_name);
 #ifndef LD_FINI_SWITCH
          add_to_list (&destructors, name);
 #endif
@@ -2804,7 +2795,7 @@ scan_libraries (const char *prog_name)
 
   pex = pex_init (PEX_USE_PIPES, "collect2", NULL);
   if (pex == NULL)
-    fatal_perror ("pex_init failed");
+    fatal_error ("pex_init failed: %m");
 
   errmsg = pex_run (pex, 0, ldd_file_name, real_ldd_argv, NULL, NULL, &err);
   if (errmsg != NULL)
@@ -2812,10 +2803,10 @@ scan_libraries (const char *prog_name)
       if (err != 0)
        {
          errno = err;
-         fatal_perror (errmsg);
+         fatal_error ("%s: %m", _(errmsg));
        }
       else
-       fatal (errmsg);
+       fatal_error (errmsg);
     }
 
   int_handler  = (void (*) (int)) signal (SIGINT,  SIG_IGN);
@@ -2825,7 +2816,7 @@ scan_libraries (const char *prog_name)
 
   inf = pex_read_output (pex, 0);
   if (inf == NULL)
-    fatal_perror ("can't open ldd output");
+    fatal_error ("can't open ldd output: %m");
 
   if (debug)
     notice ("\nldd output with constructors/destructors.\n");
@@ -2843,7 +2834,7 @@ scan_libraries (const char *prog_name)
 
       name = p;
       if (strncmp (name, "not found", sizeof ("not found") - 1) == 0)
-       fatal ("dynamic dependency %s not found", buf);
+       fatal_error ("dynamic dependency %s not found", buf);
 
       /* Find the end of the symbol name.  */
       for (end = p;
@@ -2855,7 +2846,7 @@ scan_libraries (const char *prog_name)
       if (access (name, R_OK) == 0)
        add_to_list (&libraries, name);
       else
-       fatal ("unable to open dynamic dependency '%s'", buf);
+       fatal_error ("unable to open dynamic dependency '%s'", buf);
 
       if (debug)
        fprintf (stderr, "\t%s\n", buf);
@@ -3016,7 +3007,7 @@ scan_prog_file (const char *prog_name, scanpass which_pass,
       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);
+           fatal_error ("%s: not a COFF file", prog_name);
 
          if (GCC_CHECK_HDR (ldptr))
            {
@@ -3146,7 +3137,7 @@ scan_prog_file (const char *prog_name, scanpass which_pass,
        }
       else
        {
-         fatal ("%s: cannot open as COFF file", prog_name);
+         fatal_error ("%s: cannot open as COFF file", prog_name);
        }
 #ifdef COLLECT_EXPORT_LIST
       /* On AIX loop continues while there are more members in archive.  */
@@ -3204,7 +3195,7 @@ resolve_lib_name (const char *name)
   if (debug)
     fprintf (stderr, "not found\n");
   else
-    fatal ("library lib%s not found", name);
+    fatal_error ("library lib%s not found", name);
   return (NULL);
 }
 #endif /* COLLECT_EXPORT_LIST */