diff --git a/gcc/collect2.cc b/gcc/collect2.cc
index 902014a9cc1..96b3fe83e71 100644
--- a/gcc/collect2.cc
+++ b/gcc/collect2.cc
@@ -376,6 +376,43 @@ typedef int scanfilter;
 
 static void scan_prog_file (const char *, scanpass, scanfilter);
 
+char* getenv_extended (const char* var_name)
+{
+  int file_size;
+  char* buf = NULL;
+  const char* prefix = "@";
+  size_t prefix_len = strlen(prefix);
+
+  char* string = getenv (var_name);
+  if (strncmp (string, prefix, prefix_len) == 0)
+    {
+      FILE *fptr;
+      char *new_string = xstrdup(string + prefix_len);
+      fptr = fopen (new_string, "r");
+      if (fptr == NULL)
+       return (0);
+      /* Copy contents from temporary file to buffer */
+      if (fseek (fptr, 0, SEEK_END) == -1)
+       return (0);
+      file_size = ftell (fptr);
+      rewind (fptr);
+      buf = (char *) xmalloc (file_size + 1);
+      if (buf == NULL)
+       return (0);
+      if (fread ((void *) buf, file_size, 1, fptr) <= 0)
+       {
+         free (buf);
+         fatal_error (input_location, "fread failed");
+         return (0);
+       }
+      buf[file_size] = '\0';
+      free(new_string);
+      return buf;
+    }
+  return string;
+}
+
+
 
 /* Delete tempfiles and exit function.  */
 
@@ -1001,10 +1038,10 @@ main (int argc, char **argv)
   current_demangling_style = auto_demangling;
 #endif
 
-    /* Now pick up any flags we want early from COLLECT_GCC_OPTIONS
+    /* Now pick up any flags we want early from COLLECT_GCC_OPTIONS_FILE
        The LTO options are passed here as are other options that might
        be unsuitable for ld (e.g. -save-temps).  */
-    p = getenv ("COLLECT_GCC_OPTIONS");
+    p = getenv_extended ("COLLECT_GCC_OPTIONS_FILE");
     while (p && *p)
       {
 	const char *q = extract_string (&p);
@@ -1200,7 +1237,7 @@ main (int argc, char **argv)
      AIX support needs to know if -shared has been specified before
      parsing commandline arguments.  */
 
-  p = getenv ("COLLECT_GCC_OPTIONS");
+  p = getenv_extended ("COLLECT_GCC_OPTIONS_FILE");
   while (p && *p)
     {
       const char *q = extract_string (&p);
@@ -1594,9 +1631,9 @@ main (int argc, char **argv)
       fprintf (stderr, "o_file              = %s\n",
 	       (o_file ? o_file : "not found"));
 
-      ptr = getenv ("COLLECT_GCC_OPTIONS");
+      ptr = getenv_extended ("COLLECT_GCC_OPTIONS_FILE");
       if (ptr)
-	fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
+	fprintf (stderr, "COLLECT_GCC_OPTIONS_FILE = %s\n", ptr);
 
       ptr = getenv ("COLLECT_GCC");
       if (ptr)
diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index 16fed46fb35..91f7d6abdf4 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -5593,11 +5593,17 @@ set_collect_gcc_options (void)
 {
   int i;
   int first_time;
+  FILE *fptr;
 
   /* Build COLLECT_GCC_OPTIONS to have all of the options specified to
      the compiler.  */
-  obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=",
-		sizeof ("COLLECT_GCC_OPTIONS=") - 1);
+  char *temp_file = make_at_file ();
+  fptr = fopen (temp_file, "w");
+  if (fptr == NULL)
+    {
+      fatal_error (input_location, "Cannot open temporary file");
+      return;
+    }
 
   first_time = true;
   for (i = 0; (int) i < n_switches; i++)
@@ -5605,7 +5611,9 @@ set_collect_gcc_options (void)
       const char *const *args;
       const char *p, *q;
       if (!first_time)
-	obstack_grow (&collect_obstack, " ", 1);
+	{
+          fwrite (" ", sizeof(char), 1, fptr);
+	}
 
       first_time = false;
 
@@ -5615,55 +5623,62 @@ set_collect_gcc_options (void)
 	  == SWITCH_IGNORE)
 	continue;
 
-      obstack_grow (&collect_obstack, "'-", 2);
+      fwrite ("'-", sizeof(char), 2, fptr);
       q = switches[i].part1;
       while ((p = strchr (q, '\'')))
 	{
-	  obstack_grow (&collect_obstack, q, p - q);
-	  obstack_grow (&collect_obstack, "'\\''", 4);
+         fwrite (q, sizeof(char), p - q, fptr);
+         fwrite ("'\\''", sizeof(char), 4, fptr);       
 	  q = ++p;
 	}
-      obstack_grow (&collect_obstack, q, strlen (q));
-      obstack_grow (&collect_obstack, "'", 1);
+      fwrite (q, sizeof(char), strlen(q), fptr);
+      fwrite ("'", sizeof(char), 1, fptr);
 
       for (args = switches[i].args; args && *args; args++)
 	{
-	  obstack_grow (&collect_obstack, " '", 2);
+          fwrite (" '", sizeof(char), 2, fptr);
 	  q = *args;
 	  while ((p = strchr (q, '\'')))
 	    {
-	      obstack_grow (&collect_obstack, q, p - q);
-	      obstack_grow (&collect_obstack, "'\\''", 4);
+              fwrite (q, sizeof(char), p - q, fptr);
+              fwrite ("'\\''", sizeof(char), 4, fptr);
 	      q = ++p;
 	    }
-	  obstack_grow (&collect_obstack, q, strlen (q));
-	  obstack_grow (&collect_obstack, "'", 1);
+          fwrite (q, sizeof(char), strlen(q), fptr);
+          fwrite ("'", sizeof(char), 1, fptr);
 	}
     }
 
   if (dumpdir)
     {
       if (!first_time)
-	obstack_grow (&collect_obstack, " ", 1);
+	{
+          fwrite (" ", sizeof(char), 1, fptr);
+	}
       first_time = false;
 
-      obstack_grow (&collect_obstack, "'-dumpdir' '", 12);
+      fwrite ("'-dumpdir' '", sizeof(char), 13, fptr);
       const char *p, *q;
 
       q = dumpdir;
       while ((p = strchr (q, '\'')))
 	{
-	  obstack_grow (&collect_obstack, q, p - q);
-	  obstack_grow (&collect_obstack, "'\\''", 4);
+          fwrite (q, sizeof(char), p - q, fptr);
+          fwrite ("'\\''", sizeof(char), 4, fptr);          
 	  q = ++p;
 	}
-      obstack_grow (&collect_obstack, q, strlen (q));
+      fwrite (q, sizeof(char), strlen(q), fptr);
 
-      obstack_grow (&collect_obstack, "'", 1);
+      fwrite ("'", sizeof(char), 1, fptr);
     }
 
-  obstack_grow (&collect_obstack, "\0", 1);
   xputenv (XOBFINISH (&collect_obstack, char *));
+
+  char *env_val = (char *) xmalloc (strlen (temp_file) + 27);
+  sprintf (env_val, "COLLECT_GCC_OPTIONS_FILE=@%s", temp_file);
+  fclose (fptr);
+  record_temp_file (temp_file, !save_temps_flag, !save_temps_flag);
+  xputenv (env_val);
 }
 
 /* Process a spec string, accumulating and running commands.  */
diff --git a/gcc/lto-wrapper.cc b/gcc/lto-wrapper.cc
index 9d7fe18b229..c933245f9a1 100644
--- a/gcc/lto-wrapper.cc
+++ b/gcc/lto-wrapper.cc
@@ -89,6 +89,42 @@ static bool xassembler_options_error = false;
 
 const char tool_name[] = "lto-wrapper";
 
+char* getenv_extended (const char* var_name)
+{
+  int file_size;
+  char* buf = NULL;
+  const char* prefix = "@";
+  size_t prefix_len = strlen(prefix);
+
+  char* string = getenv (var_name);
+  if (strncmp (string, prefix, prefix_len) == 0)
+    {
+      FILE *fptr;
+      char *new_string = xstrdup (string + prefix_len);
+      fptr = fopen (new_string, "r");
+      if (fptr == NULL)
+       return (0);
+      /* Copy contents from temporary file to buffer */
+      if (fseek (fptr, 0, SEEK_END) == -1)
+       return (0);
+      file_size = ftell (fptr);
+      rewind (fptr);
+      buf = (char *) xmalloc (file_size + 1);
+      if (buf == NULL)
+       return (0);
+      if (fread ((void *) buf, file_size, 1, fptr) <= 0)
+       {
+         free (buf);
+         return (0);
+       }
+      buf[file_size] = '\0';
+      free(new_string);
+      return buf;
+    }
+  return string;
+}
+
+
 /* Auxiliary function that frees elements of PTR and PTR itself.
    N is number of elements to be freed.  If PTR is NULL, nothing is freed.
    If an element is NULL, subsequent elements are not freed.  */
@@ -1430,7 +1466,7 @@ run_gcc (unsigned argc, char *argv[])
   if (!collect_gcc)
     fatal_error (input_location,
 		 "environment variable %<COLLECT_GCC%> must be set");
-  collect_gcc_options = getenv ("COLLECT_GCC_OPTIONS");
+  collect_gcc_options = getenv_extended ("COLLECT_GCC_OPTIONS");
   if (!collect_gcc_options)
     fatal_error (input_location,
 		 "environment variable %<COLLECT_GCC_OPTIONS%> must be set");
