diff gcc/lto/lto-elf.c @ 63:b7f97abdc517 gcc-4.6-20100522

update gcc from gcc-4.5.0 to gcc-4.6
author ryoma <e075725@ie.u-ryukyu.ac.jp>
date Mon, 24 May 2010 12:47:05 +0900
parents 77e2b8dfacca
children
line wrap: on
line diff
--- a/gcc/lto/lto-elf.c	Fri Feb 12 23:41:23 2010 +0900
+++ b/gcc/lto/lto-elf.c	Mon May 24 12:47:05 2010 +0900
@@ -1,5 +1,5 @@
 /* LTO routines for ELF object files.
-   Copyright 2009 Free Software Foundation, Inc.
+   Copyright 2009, 2010 Free Software Foundation, Inc.
    Contributed by CodeSourcery, Inc.
 
 This file is part of GCC.
@@ -29,6 +29,22 @@
 #include "ggc.h"
 #include "lto-streamer.h"
 
+/* Cater to hosts with half-backed <elf.h> file like HP-UX.  */
+#ifndef EM_SPARC
+# define EM_SPARC 2
+#endif
+
+#ifndef EM_SPARC32PLUS
+# define EM_SPARC32PLUS 18
+#endif
+
+
+/* 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
@@ -163,7 +179,7 @@
    the start and size of each section in the .o file.  */
 
 htab_t
-lto_elf_build_section_table (lto_file *lto_file) 
+lto_obj_build_section_table (lto_file *lto_file) 
 {
   lto_elf_file *elf_file = (lto_elf_file *)lto_file;
   htab_t section_hash_table;
@@ -306,7 +322,7 @@
 /* Begin a new ELF section named NAME in the current output file.  */
 
 void
-lto_elf_begin_section (const char *name)
+lto_obj_begin_section (const char *name)
 {
   lto_elf_begin_section_with_type (name, SHT_PROGBITS);
 }
@@ -317,7 +333,7 @@
    been written.  */
 
 void
-lto_elf_append_data (const void *data, size_t len, void *block)
+lto_obj_append_data (const void *data, size_t len, void *block)
 {
   lto_elf_file *file;
   Elf_Data *elf_data;
@@ -354,7 +370,7 @@
    and sets the current output file's scn member to NULL.  */
 
 void
-lto_elf_end_section (void)
+lto_obj_end_section (void)
 {
   lto_elf_file *file;
 
@@ -367,6 +383,41 @@
 }
 
 
+/* Return true if ELF_MACHINE is compatible with the cached value of the
+   architecture and possibly update the latter.  Return false otherwise.
+
+   Note: if you want to add more EM_* cases, you'll need to provide the
+   corresponding definitions at the beginning of the file.  */
+
+static bool
+is_compatible_architecture (Elf64_Half elf_machine)
+{
+  if (cached_file_attrs.elf_machine == elf_machine)
+    return true;
+
+  switch (cached_file_attrs.elf_machine)
+    {
+    case EM_SPARC:
+      if (elf_machine == EM_SPARC32PLUS)
+	{
+	  cached_file_attrs.elf_machine = elf_machine;
+	  return true;
+	}
+      break;
+
+    case EM_SPARC32PLUS:
+      if (elf_machine == EM_SPARC)
+	return true;
+      break;
+
+    default:
+      break;
+    }
+
+  return false;
+}
+
+
 /* Validate's ELF_FILE's executable header and, if cached_file_attrs is
    uninitialized, caches the architecture.  */
 
@@ -391,8 +442,7 @@
 								\
   if (!cached_file_attrs.initialized)				\
     cached_file_attrs.elf_machine = elf_header->e_machine;	\
-								\
-  if (cached_file_attrs.elf_machine != elf_header->e_machine)	\
+  else if (!is_compatible_architecture (elf_header->e_machine))	\
     {								\
       error ("inconsistent file architecture detected");	\
       return false;						\
@@ -405,6 +455,22 @@
 DEFINE_VALIDATE_EHDR (64)
 
 
+#ifndef HAVE_ELF_GETSHDRSTRNDX
+/* elf_getshdrstrndx replacement for systems that lack it, but provide
+   either the gABI conformant or Solaris 2 variant of elf_getshstrndx
+   instead.  */
+
+static int
+elf_getshdrstrndx (Elf *elf, size_t *dst)
+{
+#ifdef HAVE_ELF_GETSHSTRNDX_GABI
+  return elf_getshstrndx (elf, dst);
+#else
+  return elf_getshstrndx (elf, dst) ? 0 : -1;
+#endif
+}
+#endif
+
 /* Validate's ELF_FILE's executable header and, if cached_file_attrs is
    uninitialized, caches the results.  Also records the section header string
    table's section index.  Returns true on success or false on failure.  */
@@ -538,34 +604,38 @@
    Returns the opened file.  */
 
 lto_file *
-lto_elf_file_open (const char *filename, bool writable)
+lto_obj_file_open (const char *filename, bool writable)
 {
   lto_elf_file *elf_file;
   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)
+  offset_p = strrchr (filename, '@');
+  if (offset_p
+      && offset_p != filename
+      && sscanf (offset_p, "@%li%n", &loffset, &consumed) >= 1
+      && strlen (offset_p) == (unsigned int)consumed)
+    {
+      fname = (char *) xmalloc (offset_p - filename + 1);
+      memcpy (fname, filename, offset_p - filename);
+      fname[offset_p - filename] = '\0';
+      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 */
+      header_offset = offset - 60;
+    }
+  else
     {
       fname = xstrdup (filename);
       offset = 0;
       header_offset = 0;
     }
-  else
-    {
-      fname = (char *) xmalloc (offset_p - filename + 1);
-      memcpy (fname, filename, offset_p - filename);
-      fname[offset_p - filename] = '\0';
-      offset_p += 3; /* skip the @0x */
-      offset = lto_parse_hex (offset_p);
-      /* 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 */
-      header_offset = offset - 60;
-    }
 
   /* Set up.  */
   elf_file = XCNEW (lto_elf_file);
@@ -574,7 +644,8 @@
   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);
@@ -633,7 +704,7 @@
 
  fail:
   if (result)
-    lto_elf_file_close (result);
+    lto_obj_file_close (result);
   return NULL;
 }
 
@@ -643,7 +714,7 @@
    any cached data buffers are freed.  */
 
 void
-lto_elf_file_close (lto_file *file)
+lto_obj_file_close (lto_file *file)
 {
   lto_elf_file *elf_file = (lto_elf_file *) file;
   struct lto_char_ptr_base *cur, *tmp;
@@ -679,7 +750,7 @@
       if (gelf_update_ehdr (elf_file->elf, ehdr_p) == 0)
 	fatal_error ("gelf_update_ehdr() failed: %s", elf_errmsg (-1));
       lto_write_stream (elf_file->shstrtab_stream);
-      lto_elf_end_section ();
+      lto_obj_end_section ();
 
       lto_set_current_out_file (old_file);
       free (elf_file->shstrtab_stream);