OSDN Git Service

2009-11-04 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / lto-plugin / lto-plugin.c
index c92ac06..3cf4e7c 100644 (file)
@@ -37,7 +37,6 @@ along with this program; see the file COPYING3.  If not see
 #include <stdlib.h>
 #include <stdio.h>
 #include <inttypes.h>
-#include <ar.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include <fcntl.h>
@@ -70,7 +69,6 @@ struct plugin_file_info
   char *name;
   void *handle;
   struct plugin_symtab symtab;
-  unsigned char temp;
 };
 
 
@@ -513,19 +511,11 @@ static enum ld_plugin_status
 cleanup_handler (void)
 {
   int t;
-  unsigned i;
   char *arguments;
   struct stat buf;
 
-  for (i = 0; i < num_claimed_files; i++)
-    {
-      struct plugin_file_info *info = &claimed_files[i];
-      if (info->temp)
-       {
-         t = unlink (info->name);
-         check (t == 0, LDPL_FATAL, "could not unlink temporary file");
-       }
-    }
+  if (debug)
+    return LDPS_OK;
 
   /* If we are being called from an error handler, it is possible
      that the arguments file is still exists. */
@@ -555,49 +545,39 @@ claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
   Elf *elf;
   struct plugin_file_info lto_file;
   Elf_Data *symtab;
-  int lto_file_fd;
 
   if (file->offset != 0)
     {
-      /* FIXME lto: lto1 should know how to handle archives. */
-      int fd;
-      off_t size = file->filesize;
-      off_t offset;
-
-      static int objnum = 0;
       char *objname;
-      int t = asprintf (&objname, "%s/obj%d.o",
-                       temp_obj_dir_name, objnum);
+      Elf *archive;
+      off_t offset;
+      /* We pass the offset of the actual file, not the archive header. */
+      int t = asprintf (&objname, "%s@%" PRId64, file->name,
+                        (int64_t) file->offset);
       check (t >= 0, LDPL_FATAL, "asprintf failed");
-      objnum++;
-
-      fd = open (objname, O_RDWR | O_CREAT, 0666);
-      check (fd > 0, LDPL_FATAL, "could not open/create temporary file");
-      offset = lseek (file->fd, file->offset, SEEK_SET);
-      check (offset == file->offset, LDPL_FATAL, "could not seek");
-      while (size > 0)
-       {
-         ssize_t r, written;
-         char buf[1000];
-         off_t s = sizeof (buf) < size ? sizeof (buf) : size;
-         r = read (file->fd, buf, s);
-         written = write (fd, buf, r);
-         check (written == r, LDPL_FATAL, "could not write to temporary file");
-         size -= r;
-       }
       lto_file.name = objname;
-      lto_file_fd = fd;
-      lto_file.handle = file->handle;
-      lto_file.temp = 1;
+
+      archive = elf_begin (file->fd, ELF_C_READ, NULL);
+      check (elf_kind (archive) == ELF_K_AR, LDPL_FATAL,
+             "Not an archive and offset not 0");
+
+      /* elf_rand expects the offset to point to the ar header, not the
+         object itself. Subtract the size of the ar header (60 bytes).
+         We don't uses sizeof (struct ar_hd) to avoid including ar.h */
+
+      offset = file->offset - 60;
+      check (offset == elf_rand (archive, offset), LDPL_FATAL,
+             "could not seek in archive");
+      elf = elf_begin (file->fd, ELF_C_READ, archive);
+      check (elf != NULL, LDPL_FATAL, "could not find archive member");
+      elf_end (archive);
     }
   else
     {
       lto_file.name = strdup (file->name);
-      lto_file_fd = file->fd;
-      lto_file.handle = file->handle;
-      lto_file.temp = 0;
+      elf = elf_begin (file->fd, ELF_C_READ, NULL);
     }
-  elf = elf_begin (lto_file_fd, ELF_C_READ, NULL);
+  lto_file.handle = file->handle;
 
   *claimed = 0;
 
@@ -624,20 +604,12 @@ claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
   goto cleanup;
 
  err:
-  if (file->offset != 0)
-    {
-      int t = unlink (lto_file.name);
-      check (t == 0, LDPL_FATAL, "could not unlink file");
-    }
   free (lto_file.name);
 
  cleanup:
   if (elf)
     elf_end (elf);
 
-  if (file->offset != 0)
-    close (lto_file_fd);
-
   return LDPS_OK;
 }