This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[lto][patch] Call lto-wrapper from the plugin
- From: Rafael Espindola <espindola at google dot com>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Cc: Diego Novillo <dnovillo at google dot com>
- Date: Mon, 1 Dec 2008 18:05:13 +0000
- Subject: [lto][patch] Call lto-wrapper from the plugin
The attached patch makes the plugin call lto-wrapper. It should behave
almost identically to collect2, including not passing -fresolution to
gcc. For now, the only difference is that archives are extracted.
The next thing is adding an option to collect2 to make it call the
linker with the -plugin argument. Right now it is necessary to copy
and paste the collect2 line and add the -plugin option :-)
2008-12-01 Rafael Avila de Espindola <espindola@google.com>
* lto-plugin.c: Include sys/types.h and sys/wait.h
(output_files, num_output_files, lto_wrapper_argv,
lto_wrapper_num_args): New.
(free_2): Free output_files.
(write_resolution): Disable.
(add_output_files): New.
(exec_lto_wrapper): New.
(all_symbols_read_handler): Run lto-wrapper.
(claim_file_handler): Free lto_file.name and call elf_end.
(process_option): New.
Cheers,
--
Rafael Avila de Espindola
Google | Gordon House | Barrow Street | Dublin 4 | Ireland
Registered in Dublin, Ireland | Registration Number: 368047
diff --git a/lto-plugin/lto-plugin.c b/lto-plugin/lto-plugin.c
index 9c0a640..c5543a5 100644
--- a/lto-plugin/lto-plugin.c
+++ b/lto-plugin/lto-plugin.c
@@ -36,6 +36,8 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
#ifdef HAVE_GELF_H
# include <gelf.h>
@@ -85,6 +87,12 @@ static ld_plugin_add_input_file add_input_file;
static struct plugin_file_info *claimed_files = NULL;
static unsigned int num_claimed_files = 0;
+static char **output_files = NULL;
+static unsigned int num_output_files = 0;
+
+static char **lto_wrapper_argv;
+static int lto_wrapper_num_args;
+
/* Parse an entry of the IL symbol table. The data to be parsed is pointed
by P and the result is written in ENTRY. The slot number is stored in SLOT.
Returns the address of the next entry. */
@@ -245,6 +253,11 @@ free_2 (void)
free (symtab->slots);
free (info->name);
}
+
+ for (i = 0; i < num_output_files; i++)
+ free (output_files[i]);
+ free (output_files);
+
free (claimed_files);
claimed_files = NULL;
num_claimed_files = 0;
@@ -259,8 +272,13 @@ static void
write_resolution(void)
{
unsigned int i;
+ FILE *f;
+ /* FIXME: Disabled for now since we are not using the resolution file. */
+ return;
+
+
/* FIXME: This should be a temporary file. */
- FILE *f = fopen ("resolution", "w");
+ f = fopen ("resolution", "w");
fprintf (f, "%d\n", num_claimed_files);
@@ -288,23 +306,112 @@ write_resolution(void)
fclose (f);
}
+/* Pass files generated by the lto-wrapper to the linker. FD is lto-wrapper's
+ stdout. */
+
+static void
+add_output_files (int fd)
+{
+ char fname[1000]; /* FIXME: Is this big enough? */
+ int t;
+ FILE *f = fdopen (fd, "r");
+
+ for (;;)
+ {
+ size_t len;
+ char *s =fgets (fname, sizeof (fname), f);
+ if (!s)
+ break;
+
+ len = strlen (s);
+ assert (s[len - 1] == '\n');
+ s[len - 1] = '\0';
+
+ num_output_files++;
+ output_files = realloc (output_files, num_output_files * sizeof (char *));
+ output_files[num_output_files - 1] = strdup (s);
+ add_input_file (output_files[num_output_files - 1]);
+ }
+
+ t = fclose (f);
+ assert (t == 0);
+}
+
+/* Execute the lto-wrapper. ARGV[0] is the binary. The rest of ARGV is the
+ argument list. */
+
+static void
+exec_lto_wrapper (char *const argv[])
+{
+ int pipefd[2];
+ int pid;
+ int pipe_read;
+ int pipe_write;
+ int t = pipe (pipefd);
+ assert (t == 0);
+ pipe_read = pipefd[0];
+ pipe_write = pipefd[1];
+
+ pid= fork ();
+ assert (pid >= 0);
+ if (pid == 0)
+ {
+ t = close (1);
+ assert (t == 0);
+ t = close (pipe_read);
+ assert (t == 0);
+ t = dup2(pipe_write, 1);
+ assert (t == 1);
+ execv (argv[0], argv);
+ perror ("error: ");
+ exit (1);
+ }
+ else
+ {
+ int status;
+ int p;
+
+ t = close (pipe_write);
+ assert (t == 0);
+
+ add_output_files (pipe_read);
+
+ p = wait (&status);
+ assert (p == pid);
+ assert (WIFEXITED (status) && WEXITSTATUS (status) == 0);
+ }
+}
+
+
/* Called by the linker once all symbols have been read. */
static enum ld_plugin_status
all_symbols_read_handler (void)
{
unsigned i;
+ unsigned num_lto_args = num_claimed_files + lto_wrapper_num_args + 1;
+ char **lto_argv = (char **) calloc (sizeof (char *), num_lto_args);
+ const char **lto_arg_ptr = (const char **) lto_argv;
+
free_1 ();
write_resolution ();
+ for (i = 0; i < lto_wrapper_num_args; i++)
+ *lto_arg_ptr++ = lto_wrapper_argv[i];
+
for (i = 0; i < num_claimed_files; i++)
{
struct plugin_file_info *info = &claimed_files[i];
- /* FIXME: actually run wpa :-) */
- add_input_file (info->name);
+ *lto_arg_ptr++ = info->name;
}
+
+ *lto_arg_ptr++ = NULL;
+ exec_lto_wrapper (lto_argv);
+
+ free (lto_argv);
+
return LDPS_OK;
}
@@ -417,9 +524,44 @@ claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
int t = unlink (lto_file.name);
assert (t == 0);
}
+ free (lto_file.name);
+ if (elf)
+ elf_end (elf);
+
return LDPS_OK;
}
+/* Parse the lto=... OPTION. */
+
+static void
+process_option (const char *option)
+{
+ unsigned i;
+ char *p;
+
+ assert (strncmp("lto=", option, 4) == 0);
+ p = strdup(option + 4);
+
+ lto_wrapper_num_args = 1;
+ for (i = 0; p[i] != '\0'; i++)
+ if (p[i] == ' ')
+ lto_wrapper_num_args++;
+
+ lto_wrapper_argv = (char **) calloc (sizeof (char *), lto_wrapper_num_args);
+ char **lto_arg_ptr = (char **) lto_wrapper_argv;
+
+ *lto_arg_ptr++ = p;
+ for (i = 0; p[i] != '\0'; i++)
+ {
+ if (p[i] == ' ')
+ {
+ p[i] = '\0';
+ i++;
+ *lto_arg_ptr++ = &p[i];
+ }
+ }
+}
+
/* Called by gold after loading the plugin. TV is the transfer vector. */
void
@@ -455,6 +597,9 @@ onload (struct ld_plugin_tv *tv)
case LDPT_ADD_INPUT_FILE:
add_input_file = p->tv_u.tv_add_input_file;
break;
+ case LDPT_OPTION:
+ process_option (p->tv_u.tv_string);
+ break;
default:
break;
}