This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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;
 	}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]