[PATCH] GCC: Enable very long gcc command line options - PR111527
From: Deepthi Hemraj For excessively long environment variables i.e >128KB Store the arguments in a temporary file and collect them back together in collect2. This commit patches for COLLECT_GCC_OPTIONS issue: GCC should not limit the length of command line passed to collect2 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111527 The Linux kernel has the following limits on shell commands: I. Total number of bytes used to specify arguments must be under 128KB. II. Each environment variable passed to an executable must be under 128 KiB In order to circumvent these limitations, many build tools support response-files, i.e. files that contain the arguments for the executed command. These are typically passed using @ syntax. 1: In gcc, the command line arguments passed to subprocesses are controlled by 'spec-files'. The default spec for cc1plus includes the spec of CPP (C-preprocessor). Instead of passing the include directory as path to a response file to the CPP, gcc expanded it and passed them as a long string. The same problem was in the assembler (as). https://gcc.gnu.org/onlinedocs/gcc/Spec-Files.html 2: Gcc uses the COLLECT_GCC_OPTIONS environment variable to transfer the expanded command line to collect2. With many options, this exceeds the limit II. GCC : Added new Testcase for PR111527 PR111527-2.c : If the command line argument less than 128kb, gcc should use COLLECT_GCC_OPTION to communicate and compile fine. PR111527-3.c : If the command line argument in the range of 128kb to 2mb, gcc should copy arguments in a file and use FILE_GCC_OPTIONS to communicate and compile fine. PR111527-4.c : If the command line argument greater than 2mb, gcc should fail the compile and report an error. (Expected FAIL) Signed-off-by: Topi Kuutela Signed-off-by: Sunil Dora --- gcc/collect2.cc | 38 +-- gcc/gcc.cc| 36 -- gcc/testsuite/gcc.dg/longcmd/longcmd.exp | 16 gcc/testsuite/gcc.dg/longcmd/pr111527-1.c | 46 +++ gcc/testsuite/gcc.dg/longcmd/pr111527-2.c | 12 ++ gcc/testsuite/gcc.dg/longcmd/pr111527-3.c | 13 +++ gcc/testsuite/gcc.dg/longcmd/pr111527-4.c | 11 ++ 7 files changed, 166 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/longcmd/longcmd.exp create mode 100644 gcc/testsuite/gcc.dg/longcmd/pr111527-1.c create mode 100644 gcc/testsuite/gcc.dg/longcmd/pr111527-2.c create mode 100644 gcc/testsuite/gcc.dg/longcmd/pr111527-3.c create mode 100644 gcc/testsuite/gcc.dg/longcmd/pr111527-4.c Signed-off-by: Deepthi Hemraj --- gcc/collect2.cc | 38 +-- gcc/gcc.cc| 36 -- gcc/testsuite/gcc.dg/longcmd/longcmd.exp | 16 gcc/testsuite/gcc.dg/longcmd/pr111527-1.c | 46 +++ gcc/testsuite/gcc.dg/longcmd/pr111527-2.c | 12 ++ gcc/testsuite/gcc.dg/longcmd/pr111527-3.c | 13 +++ gcc/testsuite/gcc.dg/longcmd/pr111527-4.c | 11 ++ 7 files changed, 166 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/longcmd/longcmd.exp create mode 100644 gcc/testsuite/gcc.dg/longcmd/pr111527-1.c create mode 100644 gcc/testsuite/gcc.dg/longcmd/pr111527-2.c create mode 100644 gcc/testsuite/gcc.dg/longcmd/pr111527-3.c create mode 100644 gcc/testsuite/gcc.dg/longcmd/pr111527-4.c diff --git a/gcc/collect2.cc b/gcc/collect2.cc index 902014a9cc1..c45a13075d5 100644 --- a/gcc/collect2.cc +++ b/gcc/collect2.cc @@ -375,6 +375,38 @@ typedef int scanfilter; same format, and begins at __DTOR_LIST__. */ static void scan_prog_file (const char *, scanpass, scanfilter); +char* getenv_extended(const char* var_name) +{ + int file_size; + char* buf = NULL; + + char* string = getenv(var_name); + if (!string) +{ + char* string = getenv("FILE_GCC_OPTIONS"); + FILE *fptr; + fptr = fopen(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'; + return buf; +} + return string; +} /* Delete tempfiles and exit function. */ @@ -1004,7 +1036,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"); +
[PATCH] GCC Driver : Enable very long gcc command-line option
From: sunil dora For excessively long environment variables i.e >128KB Store the arguments in a temporary file and collect them back together in collect2. This commit patches for COLLECT_GCC_OPTIONS issue: GCC should not limit the length of command line passed to collect2. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111527 The Linux kernel has the following limits on shell commands: I. Total number of bytes used to specify arguments must be under 128KB. II. Each environment variable passed to an executable must be under 128 KiB In order to circumvent these limitations, many build tools support response-files, i.e. files that contain the arguments for the executed command. These are typically passed using @ syntax. Gcc uses the COLLECT_GCC_OPTIONS environment variable to transfer the expanded command line to collect2. With many options, this exceeds the limit II. GCC : Added Testcase for PR111527 TC1 : If the command line argument less than 128kb, gcc should use COLLECT_GCC_OPTION to communicate and compile fine. TC2 : If the command line argument in the range of 128kb to 2mb, gcc should copy arguments in a file and use FILE_GCC_OPTIONS to communicate and compile fine. TC3 : If the command line argument greater thean 2mb, gcc shuld fail the compile and report error. (Expected FAIL) Signed-off-by: Topi Kuutela Signed-off-by: sunil dora --- gcc/collect2.cc | 40 +++-- gcc/gcc.cc| 37 +-- gcc/testsuite/gcc.dg/longcmd/longcmd.exp | 16 + gcc/testsuite/gcc.dg/longcmd/pr111527-1.c | 44 +++ gcc/testsuite/gcc.dg/longcmd/pr111527-2.c | 9 + gcc/testsuite/gcc.dg/longcmd/pr111527-3.c | 10 ++ gcc/testsuite/gcc.dg/longcmd/pr111527-4.c | 10 ++ 7 files changed, 160 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/longcmd/longcmd.exp create mode 100644 gcc/testsuite/gcc.dg/longcmd/pr111527-1.c create mode 100644 gcc/testsuite/gcc.dg/longcmd/pr111527-2.c create mode 100644 gcc/testsuite/gcc.dg/longcmd/pr111527-3.c create mode 100644 gcc/testsuite/gcc.dg/longcmd/pr111527-4.c diff --git a/gcc/collect2.cc b/gcc/collect2.cc index 902014a9cc1..564d8968648 100644 --- a/gcc/collect2.cc +++ b/gcc/collect2.cc @@ -376,6 +376,40 @@ 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; + + char* string = getenv (var_name); + if (!string) +{ + char* string = getenv ("FILE_GCC_OPTIONS"); + FILE *fptr; + fptr = fopen (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'; + return buf; +} + return string; +} + + /* Delete tempfiles and exit function. */ @@ -1004,7 +1038,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 +1234,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 +1628,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 abdb40bfe6e..fb36d4a979c 100644 --- a/gcc/gcc.cc +++ b/gcc/gcc.cc @@ -2952,12 +2952,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; + size_t count; + FILE *fptr; + + const size_t string_leng
[PATCH v2] GCC Driver : Enable very long gcc command-line option
From: Deepthi Hemraj For excessively long environment variables i.e >128KB Store the arguments in a temporary file and collect them back together in collect2. This commit patches for COLLECT_GCC_OPTIONS issue: GCC should not limit the length of command line passed to collect2. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111527 The Linux kernel has the following limits on shell commands: I. Total number of bytes used to specify arguments must be under 128KB. II. Each environment variable passed to an executable must be under 128 KiB In order to circumvent these limitations, many build tools support response-files, i.e. files that contain the arguments for the executed command. These are typically passed using @ syntax. Gcc uses the COLLECT_GCC_OPTIONS environment variable to transfer the expanded command line to collect2. With many options, this exceeds the limit II. GCC : Added Testcase for PR111527 TC1 : If the command line argument less than 128kb, gcc should use COLLECT_GCC_OPTION to communicate and compile fine. TC2 : If the command line argument in the range of 128kb to 2mb, gcc should copy arguments in a file and use FILE_GCC_OPTIONS to communicate and compile fine. TC3 : If the command line argument greater thean 2mb, gcc shuld fail the compile and report error. (Expected FAIL) Signed-off-by: sunil dora Signed-off-by: Topi Kuutela Signed-off-by: Deepthi Hemraj --- gcc/collect2.cc | 39 ++-- gcc/gcc.cc| 37 +-- gcc/testsuite/gcc.dg/longcmd/longcmd.exp | 16 + gcc/testsuite/gcc.dg/longcmd/pr111527-1.c | 44 +++ gcc/testsuite/gcc.dg/longcmd/pr111527-2.c | 9 + gcc/testsuite/gcc.dg/longcmd/pr111527-3.c | 10 ++ gcc/testsuite/gcc.dg/longcmd/pr111527-4.c | 10 ++ 7 files changed, 159 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/longcmd/longcmd.exp create mode 100644 gcc/testsuite/gcc.dg/longcmd/pr111527-1.c create mode 100644 gcc/testsuite/gcc.dg/longcmd/pr111527-2.c create mode 100644 gcc/testsuite/gcc.dg/longcmd/pr111527-3.c create mode 100644 gcc/testsuite/gcc.dg/longcmd/pr111527-4.c diff --git a/gcc/collect2.cc b/gcc/collect2.cc index 902014a9cc1..1f56963b1ce 100644 --- a/gcc/collect2.cc +++ b/gcc/collect2.cc @@ -376,6 +376,39 @@ 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 = "/tmp"; + + char* string = getenv (var_name); + if (strncmp (var_name, prefix, strlen(prefix)) == 0) +{ + FILE *fptr; + fptr = fopen (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'; + return buf; +} + return string; +} + /* Delete tempfiles and exit function. */ @@ -1004,7 +1037,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 +1233,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 +1627,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 d07a8e172a4..3d7fd8dff5b 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 standa
[PATCH v3] GCC Driver : Enable very long gcc command-line option
From: Deepthi Hemraj For excessively long environment variables i.e >128KB Store the arguments in a temporary file and collect them back together in collect2. This commit patches for COLLECT_GCC_OPTIONS issue: GCC should not limit the length of command line passed to collect2. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111527 The Linux kernel has the following limits on shell commands: I. Total number of bytes used to specify arguments must be under 128KB. II. Each environment variable passed to an executable must be under 128 KiB In order to circumvent these limitations, many build tools support response-files, i.e. files that contain the arguments for the executed command. These are typically passed using @ syntax. Gcc uses the COLLECT_GCC_OPTIONS environment variable to transfer the expanded command line to collect2. With many options, this exceeds the limit II. GCC : Added Testcase for PR111527 TC1 : If the command line argument less than 128kb, gcc should use COLLECT_GCC_OPTION to communicate and compile fine. TC2 : If the command line argument in the range of 128kb to 2mb, gcc should copy arguments in a file and use FILE_GCC_OPTIONS to communicate and compile fine. TC3 : If the command line argument greater thean 2mb, gcc shuld fail the compile and report error. (Expected FAIL) Signed-off-by: sunil dora Signed-off-by: Topi Kuutela --- gcc/collect2.cc | 42 -- gcc/gcc.cc| 37 +-- gcc/testsuite/gcc.dg/longcmd/longcmd.exp | 16 + gcc/testsuite/gcc.dg/longcmd/pr111527-1.c | 44 +++ gcc/testsuite/gcc.dg/longcmd/pr111527-2.c | 9 + gcc/testsuite/gcc.dg/longcmd/pr111527-3.c | 10 ++ gcc/testsuite/gcc.dg/longcmd/pr111527-4.c | 10 ++ 7 files changed, 162 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/longcmd/longcmd.exp create mode 100644 gcc/testsuite/gcc.dg/longcmd/pr111527-1.c create mode 100644 gcc/testsuite/gcc.dg/longcmd/pr111527-2.c create mode 100644 gcc/testsuite/gcc.dg/longcmd/pr111527-3.c create mode 100644 gcc/testsuite/gcc.dg/longcmd/pr111527-4.c diff --git a/gcc/collect2.cc b/gcc/collect2.cc index 902014a9cc1..5b5f16ab46c 100644 --- a/gcc/collect2.cc +++ b/gcc/collect2.cc @@ -376,6 +376,42 @@ 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 +1040,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 +1236,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 +1630,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 ae1d80fe00a..98c1dff6335 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. */ +/* A