diff --git a/gcc/collect2.cc b/gcc/collect2.cc
index 902014a9cc1..bc0ef7d144e 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.  */
 
@@ -1004,7 +1041,7 @@ main (int argc, char **argv)
     /* Now pick up any flags we want early from COLLECT_GCC_OPTIONS
        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");
     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");
   while (p && *p)
     {
       const char *q = extract_string (&p);
@@ -1594,7 +1631,7 @@ 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");
       if (ptr)
 	fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
 
diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index 16fed46fb35..3ba1481a29b 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -2953,12 +2953,43 @@ add_to_obstack (char *path, void *data)
   return NULL;
 }
 
-/* Add or change the value of an environment variable, outputting the
-   change to standard error if in verbose mode.  */
+/* Add or change the value of an environment variable,
+ * outputting the change to standard error if in verbose mode.  */
 static void
 xputenv (const char *string)
 {
-  env.xput (string);
+  static const size_t MAX_ENV_VAR_LEN = 128*1024;
+  const char *prefix = "COLLECT_GCC_OPTIONS=";
+  size_t prefix_len = strlen (prefix);
+  FILE *fptr;
+
+  const size_t string_length = strlen (string);
+  if ( string_length < MAX_ENV_VAR_LEN )
+    {
+      env.xput (string);
+      return;
+    }
+  /*  For excessively long environment variables i.e >128KB
+      Store the arguments in a temporary file and collect
+      them back together in collect2 */
+  if (strncmp (string, prefix, prefix_len) == 0)
+    {
+      const char *data_to_write = string + prefix_len;
+      char *temp_file = make_at_file ();
+      fptr = fopen (temp_file, "w");
+      if (fptr == NULL)
+	{
+	  fatal_error (input_location, "Cannot open temporary file");
+	  return;
+	}
+      /*  Copy contents into temporary file  */
+      fwrite (data_to_write, sizeof(char), strlen(data_to_write), fptr);
+      char *env_val = (char *) xmalloc (strlen (temp_file) + strlen(prefix) + 2);
+      sprintf (env_val, "COLLECT_GCC_OPTIONS=@%s", temp_file);
+      env.xput (env_val);
+      record_temp_file (temp_file, !save_temps_flag, !save_temps_flag);
+      fclose (fptr);
+    }
 }
 
 /* Build a list of search directories from PATHS.
diff --git a/gcc/lto-wrapper.cc b/gcc/lto-wrapper.cc
index 9d7fe18b229..0013887cbac 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,8 @@ 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");
