OSDN Git Service

2010-02-11 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / lto / lto-elf.c
index ee587f7..356e513 100644 (file)
@@ -29,12 +29,20 @@ along with GCC; see the file COPYING3.  If not see
 #include "ggc.h"
 #include "lto-streamer.h"
 
+/* Handle opening elf files on hosts, such as Windows, that may use 
+   text file handling that will break binary access.  */
+
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
 
 /* Initialize FILE, an LTO file object for FILENAME.  */
 static void
-lto_file_init (lto_file *file, const char *filename)
+lto_file_init (lto_file *file, const char *filename, off_t offset)
 {
   file->filename = filename;
+  file->offset = offset;
 }
 
 /* An ELF file.  */
@@ -540,40 +548,45 @@ lto_file *
 lto_elf_file_open (const char *filename, bool writable)
 {
   lto_elf_file *elf_file;
-  lto_file *result;
+  lto_file *result = NULL;
   off_t offset;
+  long loffset;
+  off_t header_offset;
   const char *offset_p;
   char *fname;
+  int consumed;
 
-  offset_p = strchr (filename, '@');
-  if (!offset_p)
-    {
-      fname = xstrdup (filename);
-      offset = 0;
-    }
-  else
+  offset_p = strrchr (filename, '@');
+  if (offset_p
+      && offset_p != filename
+      && sscanf (offset_p, "@%li%n", &loffset, &consumed) >= 1
+      && strlen (offset_p) == (unsigned int)consumed)
     {
-      int64_t t;
       fname = (char *) xmalloc (offset_p - filename + 1);
       memcpy (fname, filename, offset_p - filename);
       fname[offset_p - filename] = '\0';
-      offset_p++;
-      sscanf(offset_p, "%" PRId64 , &t);
-      offset = t;
+      offset = (off_t)loffset;
       /* 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 -= 60;
+      header_offset = offset - 60;
+    }
+  else
+    {
+      fname = xstrdup (filename);
+      offset = 0;
+      header_offset = 0;
     }
 
   /* Set up.  */
   elf_file = XCNEW (lto_elf_file);
   result = (lto_file *) elf_file;
-  lto_file_init (result, fname);
+  lto_file_init (result, fname, offset);
   elf_file->fd = -1;
 
   /* Open the file.  */
-  elf_file->fd = open (fname, writable ? O_WRONLY|O_CREAT : O_RDONLY, 0666);
+  elf_file->fd = open (fname, writable ? O_WRONLY|O_CREAT|O_BINARY 
+                                      : O_RDONLY|O_BINARY, 0666);
   if (elf_file->fd == -1)
     {
       error ("could not open file %s", fname);
@@ -599,8 +612,8 @@ lto_elf_file_open (const char *filename, bool writable)
   if (offset != 0)
     {
       Elf *e;
-      off_t t = elf_rand (elf_file->elf, offset);
-      if (t != offset)
+      off_t t = elf_rand (elf_file->elf, header_offset);
+      if (t != header_offset)
         {
           error ("could not seek in archive");
           goto fail;
@@ -631,7 +644,8 @@ lto_elf_file_open (const char *filename, bool writable)
   return result;
 
  fail:
-  lto_elf_file_close (result);
+  if (result)
+    lto_elf_file_close (result);
   return NULL;
 }