Hi, Previously, the lto-wrapper communicates with ld by creating a pipe from lto-wrapper's stdout to ld's stdin. This patch uses a temporary file for this communication, releasing stdout to be used for debugging.
I've run a full testsuite and bootstrapped LTO in a linux x86_64, and found no issues so far. Do I need to write a testcase for this feature? Giuliano. gcc/ChangeLog 2019-10-16 Giuliano Belinassi <giuliano.belina...@usp.br> * lto-wrapper.c (STATIC_LEN): New macro. (to_ld): New. (find_crtofftable): Print to file to_ld. (find_ld_list_file): New. (main): Check if to_ld is valid or is stdout. gcc/libiberty 2019-10-16 Giuliano Belinassi <giuliano.belina...@usp.br> * pex-unix.c (pex_unix_exec_child): check for PEX_KEEP_STD_IO flag. (to_ld): New. gcc/include 19-10-16 Giuliano Belinassi <giuliano.belina...@usp.br> * libiberty.h (PEX_KEEP_STD_IO): New macro. gcc/lto-plugin 2019-10-16 Giuliano Belinassi <giuliano.belina...@usp.br> * lto-plugin.c (exec_lto_wrapper): Replace pipe from stdout to temporary file, and pass its name in argv.
diff --git gcc/lto-wrapper.c gcc/lto-wrapper.c index 9a7bbd0c022..d794b493d5d 100644 --- gcc/lto-wrapper.c +++ gcc/lto-wrapper.c @@ -49,6 +49,8 @@ along with GCC; see the file COPYING3. If not see #include "lto-section-names.h" #include "collect-utils.h" +#define STATIC_LEN(x) (sizeof (x) / sizeof (*x)) + /* Environment variable, used for passing the names of offload targets from GCC driver to lto-wrapper. */ #define OFFLOAD_TARGET_NAMES_ENV "OFFLOAD_TARGET_NAMES" @@ -74,6 +76,8 @@ static char *makefile; static unsigned int num_deb_objs; static const char **early_debug_object_names; +static FILE *to_ld; + const char tool_name[] = "lto-wrapper"; /* Delete tempfiles. Called from utils_cleanup. */ @@ -955,7 +959,7 @@ find_crtoffloadtable (void) /* The linker will delete the filename we give it, so make a copy. */ char *crtoffloadtable = make_temp_file (".crtoffloadtable.o"); copy_file (crtoffloadtable, paths[i]); - printf ("%s\n", crtoffloadtable); + fprintf (to_ld, "%s\n", crtoffloadtable); XDELETEVEC (crtoffloadtable); break; } @@ -1556,7 +1560,7 @@ cont1: { find_crtoffloadtable (); for (i = 0; offload_names[i]; i++) - printf ("%s\n", offload_names[i]); + fprintf (to_ld, "%s\n", offload_names[i]); free_array_of_ptrs ((void **) offload_names, i); } } @@ -1686,12 +1690,12 @@ cont1: if (lto_mode == LTO_MODE_LTO) { - printf ("%s\n", flto_out); + fprintf (to_ld, "%s\n", flto_out); if (!skip_debug) { for (i = 0; i < ltoobj_argc; ++i) if (early_debug_object_names[i] != NULL) - printf ("%s\n", early_debug_object_names[i]); + fprintf (to_ld, "%s\n", early_debug_object_names[i]); } /* These now belong to collect2. */ free (flto_out); @@ -1866,15 +1870,15 @@ cont: } for (i = 0; i < nr; ++i) { - fputs (output_names[i], stdout); - putc ('\n', stdout); + fputs (output_names[i], to_ld); + putc ('\n', to_ld); free (input_names[i]); } if (!skip_debug) { for (i = 0; i < ltoobj_argc; ++i) if (early_debug_object_names[i] != NULL) - printf ("%s\n", early_debug_object_names[i]); + fprintf (to_ld, "%s\n", early_debug_object_names[i]); } nr = 0; free (ltrans_priorities); @@ -1892,13 +1896,43 @@ cont: obstack_free (&argv_obstack, NULL); } +/* Find out if lto-wrapper was called and output to lto-plugin will be in a file + instead of stdout. */ + +static const char *find_ld_list_file (int* argc, char *argv[]) +{ + int i; + static const char param[] = "--to_ld_list="; + + for (i = 1; i < *argc; i++) + { + if (argv[i] != NULL && !strncmp (argv[i], param, STATIC_LEN (param) - 1)) + { + /* Found. Retrieve the path to the file. */ + + /* This simple 'automata' just finds the first ':' of the string, + and then return a pointer from now foward. */ + const char *path = argv[i]; + argv[i] = NULL; + (*argc)--; + while (*path != '\0') + if (*path++ == '=') + return path; + } + } + + + /* Not found. */ + return NULL; +} + /* Entry point. */ int main (int argc, char *argv[]) { - const char *p; + const char *p, *files_list; init_opts_obstack (); @@ -1934,11 +1968,22 @@ main (int argc, char *argv[]) signal (SIGCHLD, SIG_DFL); #endif + files_list = find_ld_list_file (&argc, argv); + to_ld = files_list ? fopen (files_list, "a") : stdout; + + if (!to_ld) + { + fprintf (stderr, "%s: failed to open parameter file.\n", argv[0]); + abort (); + } + /* We may be called with all the arguments stored in some file and passed with @file. Expand them into argv before processing. */ expandargv (&argc, &argv); run_gcc (argc, argv); + fclose (to_ld); + return 0; } diff --git include/libiberty.h include/libiberty.h index 71192a29377..cc3940f91f3 100644 --- include/libiberty.h +++ include/libiberty.h @@ -406,6 +406,9 @@ extern void hex_init (void); /* Save files used for communication between processes. */ #define PEX_SAVE_TEMPS 0x4 +/* Don't close the standard I/O streams (stdout & stderr). */ +#define PEX_KEEP_STD_IO 0x8 + /* Max number of alloca bytes per call before we must switch to malloc. ?? Swiped from gnulib's regex_internal.h header. Is this actually diff --git libiberty/pex-unix.c libiberty/pex-unix.c index f9e5277897b..afa5d9cc288 100644 --- libiberty/pex-unix.c +++ libiberty/pex-unix.c @@ -651,14 +651,14 @@ pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable, else if (close (in) < 0) failed.fn = "close", failed.err = errno; } - if (!failed.fn && out != STDOUT_FILE_NO) + if (!failed.fn && out != STDOUT_FILE_NO && !(flags & PEX_KEEP_STD_IO)) { if (dup2 (out, STDOUT_FILE_NO) < 0) failed.fn = "dup2", failed.err = errno; else if (close (out) < 0) failed.fn = "close", failed.err = errno; } - if (!failed.fn && errdes != STDERR_FILE_NO) + if (!failed.fn && errdes != STDERR_FILE_NO && !(flags & PEX_KEEP_STD_IO)) { if (dup2 (errdes, STDERR_FILE_NO) < 0) failed.fn = "dup2", failed.err = errno; diff --git lto-plugin/lto-plugin.c lto-plugin/lto-plugin.c index 556e3ebcf76..40d25a30cfd 100644 --- lto-plugin/lto-plugin.c +++ lto-plugin/lto-plugin.c @@ -560,9 +560,10 @@ exec_lto_wrapper (char *argv[]) char *at_args; FILE *args; FILE *wrapper_output; - char *new_argv[3]; + char *new_argv[4]; struct pex_obj *pex; const char *errmsg; + char *temp_filename; /* Write argv to a file to avoid a command line that is too long Save the file locally on save-temps. */ @@ -607,10 +608,6 @@ exec_lto_wrapper (char *argv[]) fprintf (stderr, "\n"); } - new_argv[0] = argv[0]; - new_argv[1] = at_args; - new_argv[2] = NULL; - if (debug) { for (i = 0; new_argv[i]; i++) @@ -618,26 +615,36 @@ exec_lto_wrapper (char *argv[]) fprintf (stderr, "\n"); } - pex = pex_init (PEX_USE_PIPES, "lto-wrapper", NULL); + pex = pex_init (0, "lto-wrapper", NULL); check (pex != NULL, LDPL_FATAL, "could not pex_init lto-wrapper"); - errmsg = pex_run (pex, 0, new_argv[0], new_argv, NULL, NULL, &t); - check (errmsg == NULL, LDPL_FATAL, "could not run lto-wrapper"); - check (t == 0, LDPL_FATAL, "could not run lto-wrapper"); + temp_filename = make_temp_file ("-ld-files.lto"); - wrapper_output = pex_read_output (pex, 0); - check (wrapper_output, LDPL_FATAL, "could not read lto-wrapper output"); + new_argv[0] = argv[0]; + new_argv[1] = at_args; + new_argv[2] = concat ("--to_ld_list=", temp_filename, NULL); + new_argv[3] = NULL; - add_output_files (wrapper_output); + errmsg = pex_run (pex, PEX_KEEP_STD_IO, new_argv[0], new_argv, + temp_filename, NULL, &t); + check (errmsg == NULL, LDPL_FATAL, "could not run lto-wrapper"); + check (t == 0, LDPL_FATAL, "could not run lto-wrapper"); t = pex_get_status (pex, 1, &status); check (t == 1, LDPL_FATAL, "could not get lto-wrapper exit status"); check (WIFEXITED (status) && WEXITSTATUS (status) == 0, LDPL_FATAL, "lto-wrapper failed"); - pex_free (pex); + wrapper_output = fopen (temp_filename, "r"); + check (wrapper_output, LDPL_FATAL, "could not read lto-wrapper output"); + + add_output_files (wrapper_output); + pex_free (pex); + free (temp_filename); free (at_args); + free (argv[2]); + fclose (wrapper_output); } /* Pass the original files back to the linker. */