OSDN Git Service

2009-11-04 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / lto / lto-elf.c
index 28c26c7..ee587f7 100644 (file)
@@ -167,9 +167,11 @@ lto_elf_build_section_table (lto_file *lto_file)
   lto_elf_file *elf_file = (lto_elf_file *)lto_file;
   htab_t section_hash_table;
   Elf_Scn *section;
+  size_t base_offset;
 
   section_hash_table = htab_create (37, hash_name, eq_name, free);
 
+  base_offset = elf_getbase (elf_file->elf);
   for (section = elf_getscn (elf_file->elf, 0);
        section;
        section = elf_nextscn (elf_file->elf, section)) 
@@ -206,7 +208,7 @@ lto_elf_build_section_table (lto_file *lto_file)
 
          new_slot->name = new_name;
          /* The offset into the file for this section.  */
-         new_slot->start = shdr->sh_offset;
+         new_slot->start = base_offset + shdr->sh_offset;
          new_slot->len = shdr->sh_size;
          *slot = new_slot;
        }
@@ -235,7 +237,12 @@ init_shdr##BITS (Elf_Scn *scn, size_t sh_name, size_t sh_type)           \
                                                                      \
   shdr = elf##BITS##_getshdr (scn);                                  \
   if (!shdr)                                                         \
-    fatal_error ("elf"#BITS"_getshdr() failed: %s", elf_errmsg (-1));\
+    {                                                                \
+      if (BITS == 32)                                                \
+       fatal_error ("elf32_getshdr() failed: %s", elf_errmsg (-1));  \
+      else                                                           \
+       fatal_error ("elf64_getshdr() failed: %s", elf_errmsg (-1));  \
+    }                                                                \
                                                                      \
   shdr->sh_name = sh_name;                                           \
   shdr->sh_type = sh_type;                                           \
@@ -486,7 +493,12 @@ init_ehdr##BITS (lto_elf_file *elf_file)                         \
                                                                      \
   ehdr = elf##BITS##_newehdr (elf_file->elf);                        \
   if (!ehdr)                                                         \
-    fatal_error ("elf"#BITS"_newehdr() failed: %s", elf_errmsg (-1));\
+    {                                                                \
+      if (BITS == 32)                                                \
+       fatal_error ("elf32_newehdr() failed: %s", elf_errmsg (-1));  \
+      else                                                           \
+       fatal_error ("elf64_newehdr() failed: %s", elf_errmsg (-1));  \
+    }                                                                \
                                                                      \
   memcpy (ehdr->e_ident, cached_file_attrs.elf_ident,                \
          sizeof cached_file_attrs.elf_ident);                        \
@@ -520,7 +532,6 @@ init_ehdr (lto_elf_file *elf_file)
     }
 }
 
-
 /* Open ELF file FILENAME.  If WRITABLE is true, the file is opened for write
    and, if necessary, created.  Otherwise, the file is opened for reading.
    Returns the opened file.  */
@@ -530,18 +541,42 @@ lto_elf_file_open (const char *filename, bool writable)
 {
   lto_elf_file *elf_file;
   lto_file *result;
+  off_t offset;
+  const char *offset_p;
+  char *fname;
+
+  offset_p = strchr (filename, '@');
+  if (!offset_p)
+    {
+      fname = xstrdup (filename);
+      offset = 0;
+    }
+  else
+    {
+      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;
+      /* 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;
+    }
 
   /* Set up.  */
   elf_file = XCNEW (lto_elf_file);
   result = (lto_file *) elf_file;
-  lto_file_init (result, filename);
+  lto_file_init (result, fname);
   elf_file->fd = -1;
 
   /* Open the file.  */
-  elf_file->fd = open (filename, writable ? O_WRONLY|O_CREAT : O_RDONLY, 0666);
+  elf_file->fd = open (fname, writable ? O_WRONLY|O_CREAT : O_RDONLY, 0666);
   if (elf_file->fd == -1)
     {
-      error ("could not open file %s", filename);
+      error ("could not open file %s", fname);
       goto fail;
     }
 
@@ -561,6 +596,26 @@ lto_elf_file_open (const char *filename, bool writable)
       goto fail;
     }
 
+  if (offset != 0)
+    {
+      Elf *e;
+      off_t t = elf_rand (elf_file->elf, offset);
+      if (t != offset)
+        {
+          error ("could not seek in archive");
+          goto fail;
+        }
+
+      e = elf_begin (elf_file->fd, ELF_C_READ, elf_file->elf);
+      if (e == NULL)
+        {
+          error("could not find archive member");
+          goto fail;
+        }
+      elf_end (elf_file->elf);
+      elf_file->elf = e;
+    }
+
   if (writable)
     {
       init_ehdr (elf_file);