OSDN Git Service

Backported from mainline
[pf3gnuchains/gcc-fork.git] / lto-plugin / lto-plugin.c
index 2f422a3..8d55cb8 100644 (file)
@@ -62,6 +62,14 @@ along with this program; see the file COPYING3.  If not see
 #include "simple-object.h"
 #include "plugin-api.h"
 
+/* We need to use I64 instead of ll width-specifier on native Windows.
+   The reason for this is that older MS-runtimes don't support the ll.  */
+#ifdef __MINGW32__
+#define PRI_LL "I64"
+#else
+#define PRI_LL "ll"
+#endif
+
 /* Handle opening elf files on hosts, such as Windows, that may use
    text file handling that will break binary access.  */
 #ifndef O_BINARY
@@ -80,12 +88,13 @@ along with this program; see the file COPYING3.  If not see
 
 /* The part of the symbol table the plugin has to keep track of. Note that we
    must keep SYMS until all_symbols_read is called to give the linker time to
-   copy the symbol information. */
+   copy the symbol information. 
+   The id must be 64bit to minimze collisions. */
 
 struct sym_aux
 {
   uint32_t slot;
-  unsigned id;
+  unsigned long long id;
   unsigned next_conflict;
 };
 
@@ -94,7 +103,7 @@ struct plugin_symtab
   int nsyms;
   struct sym_aux *aux;
   struct ld_plugin_symbol *syms;
-  unsigned id;
+  unsigned long long id;
 };
 
 /* Encapsulates object file data during symbol scan.  */
@@ -129,7 +138,7 @@ enum symbol_style
 static char *arguments_file_name;
 static ld_plugin_register_claim_file register_claim_file;
 static ld_plugin_register_all_symbols_read register_all_symbols_read;
-static ld_plugin_get_symbols get_symbols;
+static ld_plugin_get_symbols get_symbols, get_symbols_v2;
 static ld_plugin_register_cleanup register_cleanup;
 static ld_plugin_add_input_file add_input_file;
 static ld_plugin_add_input_library add_input_library;
@@ -152,6 +161,10 @@ static char debug;
 static char nop;
 static char *resolution_file = NULL;
 
+/* The version of gold being used, or -1 if not gold.  The number is
+   MAJOR * 100 + MINOR.  */
+static int gold_version = -1;
+
 /* Not used by default, but can be overridden at runtime
    by using -plugin-opt=-sym-style={none,win32,underscore|uscore}
    (in fact, only first letter of style arg is checked.)  */
@@ -308,8 +321,7 @@ free_1 (void)
        {
          struct ld_plugin_symbol *s = &symtab->syms[j];
          free (s->name);
-         if (s->comdat_key)
-           free (s->comdat_key);
+         free (s->comdat_key);
        }
       free (symtab->syms);
       symtab->syms = NULL;
@@ -338,8 +350,7 @@ free_2 (void)
   claimed_files = NULL;
   num_claimed_files = 0;
 
-  if (arguments_file_name)
-    free (arguments_file_name);
+  free (arguments_file_name);
   arguments_file_name = NULL;
 }
 
@@ -357,7 +368,8 @@ dump_symtab (FILE *f, struct plugin_symtab *symtab)
       
       assert (resolution != LDPR_UNKNOWN);
 
-      fprintf (f, "%u %x %s %s\n", (unsigned int) slot, symtab->aux[j].id,
+      fprintf (f, "%u %" PRI_LL "x %s %s\n",
+               (unsigned int) slot, symtab->aux[j].id,
               lto_resolution_str[resolution], 
               symtab->syms[j].name);
     }
@@ -439,7 +451,12 @@ write_resolution (void)
       struct plugin_symtab *symtab = &info->symtab;
       struct ld_plugin_symbol *syms = symtab->syms;
 
-      get_symbols (info->handle, symtab->nsyms, syms);
+      /* Version 2 of API supports IRONLY_EXP resolution that is
+         accepted by GCC-4.7 and newer.  */
+      if (get_symbols_v2)
+        get_symbols_v2 (info->handle, symtab->nsyms, syms);
+      else
+        get_symbols (info->handle, symtab->nsyms, syms);
 
       finish_conflict_resolution (symtab, &info->conflicts);
 
@@ -622,7 +639,8 @@ all_symbols_read_handler (void)
 
   free (lto_argv);
 
-  if (pass_through_items)
+  /* --pass-through is not needed when using gold 1.11 or later.  */
+  if (pass_through_items && gold_version < 111)
     {
       unsigned int i;
       for (i = 0; i < num_pass_through_items; i++)
@@ -756,7 +774,7 @@ resolve_conflicts (struct plugin_symtab *t, struct plugin_symtab *conflicts)
            {
              SWAP (struct ld_plugin_symbol, *orig, *s);
              SWAP (uint32_t, orig_aux->slot, aux->slot);
-             SWAP (unsigned, orig_aux->id, aux->id);
+             SWAP (unsigned long long, orig_aux->id, aux->id);
              /* Don't swap conflict chain pointer */
            } 
 
@@ -806,7 +824,7 @@ process_symtab (void *data, const char *name, off_t offset, off_t length)
 
   s = strrchr (name, '.');
   if (s)
-    sscanf (s, ".%x", &obj->out->id);
+    sscanf (s, ".%" PRI_LL "x", &obj->out->id);
   secdata = xmalloc (length);
   offset += obj->file->offset;
   if (offset != lseek (obj->file->fd, offset, SEEK_SET)
@@ -846,11 +864,11 @@ claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
       /* We pass the offset of the actual file, not the archive header.
          Can't use PRIx64, because that's C99, so we have to print the
         64-bit hex int as two 32-bit ones. */
-      int lo, hi;
+      int lo, hi, t;
       lo = file->offset & 0xffffffff;
       hi = ((int64_t)file->offset >> 32) & 0xffffffff;
-      int t = hi ? asprintf (&objname, "%s@0x%x%08x", file->name, lo, hi)
-               : asprintf (&objname, "%s@0x%x", file->name, lo);
+      t = hi ? asprintf (&objname, "%s@0x%x%08x", file->name, lo, hi)
+            : asprintf (&objname, "%s@0x%x", file->name, lo);
       check (t >= 0, LDPL_FATAL, "asprintf failed");
       lto_file.name = objname;
     }
@@ -983,6 +1001,9 @@ onload (struct ld_plugin_tv *tv)
        case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
          register_all_symbols_read = p->tv_u.tv_register_all_symbols_read;
          break;
+       case LDPT_GET_SYMBOLS_V2:
+         get_symbols_v2 = p->tv_u.tv_get_symbols;
+         break;
        case LDPT_GET_SYMBOLS:
          get_symbols = p->tv_u.tv_get_symbols;
          break;
@@ -998,6 +1019,9 @@ onload (struct ld_plugin_tv *tv)
        case LDPT_OPTION:
          process_option (p->tv_u.tv_string);
          break;
+       case LDPT_GOLD_VERSION:
+         gold_version = p->tv_u.tv_val;
+         break;
        default:
          break;
        }