use simple-object instead of nm to determine if files contain LTO.
authorIain Sandoe <iain@sandoe.co.uk>
Sun, 23 Dec 2018 10:43:59 +0000 (10:43 +0000)
committerIain Sandoe <iains@gcc.gnu.org>
Sun, 23 Dec 2018 10:43:59 +0000 (10:43 +0000)
This replaces the use of nm to search for the LTO common symbol marker
and uses simple object to see if there's a section starting with
".gnu.lto_." or ".gnu.offload_lto_"

2018-12-23  Iain Sandoe  <iain@sandoe.co.uk>

* collect2.c (maybe_run_lto_and_relink): Don’t say we have a temp file
unless we actually did some LTO.
(has_lto_section, is_lto_object_file): New.
(maybe_lto_object_file): Remove.
(scan_prog_file): Use is_lto_object_file() instead of scanning the
output of nm.

From-SVN: r267371

gcc/ChangeLog
gcc/collect2.c

index bdc22b70efad566430a9591e8a9a82708a3c7cdf..3691e65860e75d2e332163af544d4b21bd6970f3 100644 (file)
@@ -1,3 +1,12 @@
+2018-12-23  Iain Sandoe  <iain@sandoe.co.uk>
+
+       * collect2.c (maybe_run_lto_and_relink): Don’t say we have a temp file
+       unless we actually did some LTO.
+       (has_lto_section, is_lto_object_file): New.
+       (maybe_lto_object_file): Remove.
+       (scan_prog_file): Use is_lto_object_file() instead of scanning the
+       output of nm.
+
 2018-12-23  Iain Sandoe  <iain@sandoe.co.uk>
 
        * collect2.c (main): Parse the output file early so we can make nicer
index 60269682ecb0a2878674b9c291c14fb9e2bf765e..dcbd3e18a65776b15c455d291389adeaf8628f1e 100644 (file)
@@ -30,6 +30,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm.h"
 #include "filenames.h"
 #include "file-find.h"
+#include "simple-object.h"
+#include "lto-section-names.h"
 
 /* TARGET_64BIT may be defined to use driver specific functionality. */
 #undef TARGET_64BIT
@@ -804,7 +806,9 @@ maybe_run_lto_and_relink (char **lto_ld_argv, char **object_lst,
       /* Run the linker again, this time replacing the object files
          optimized by the LTO with the temporary file generated by the LTO.  */
       fork_execute ("ld", out_lto_ld_argv, HAVE_GNU_LD && at_file_supplied);
-      post_ld_pass (true);
+      /* We assume that temp files were created, and therefore we need to take
+         that into account (maybe run dsymutil).  */
+      post_ld_pass (/*temp_file*/true);
       free (lto_ld_argv);
 
       maybe_unlink_list (lto_o_files);
@@ -814,10 +818,11 @@ maybe_run_lto_and_relink (char **lto_ld_argv, char **object_lst,
       /* Our caller is relying on us to do the link
          even though there is no LTO back end work to be done.  */
       fork_execute ("ld", lto_ld_argv, HAVE_GNU_LD && at_file_supplied);
-      post_ld_pass (false);
+      /* No LTO objects were found, so no new temp file.  */
+      post_ld_pass (/*temp_file*/false);
     }
   else
-    post_ld_pass (true);
+    post_ld_pass (false); /* No LTO objects were found, no temp file.  */
 }
 \f
 /* Main program.  */
@@ -1710,7 +1715,7 @@ main (int argc, char **argv)
        if (lto_mode != LTO_MODE_NONE)
          maybe_run_lto_and_relink (ld1_argv, object_lst, object, false);
        else
-         post_ld_pass (false);
+         post_ld_pass (/*temp_file*/false);
 
        return 0;
       }
@@ -1780,7 +1785,7 @@ main (int argc, char **argv)
 #ifdef COLLECT_EXPORT_LIST
       maybe_unlink (export_file);
 #endif
-      post_ld_pass (false);
+      post_ld_pass (/*temp_file*/false);
 
       maybe_unlink (c_file);
       maybe_unlink (o_file);
@@ -1874,7 +1879,7 @@ main (int argc, char **argv)
   else
     {
       fork_execute ("ld", ld2_argv, HAVE_GNU_LD && at_file_supplied);
-      post_ld_pass (false);
+      post_ld_pass (/*temp_file*/false);
     }
 
   /* Let scan_prog_file do any final mods (OSF/rose needs this for
@@ -2332,38 +2337,52 @@ write_aix_file (FILE *stream, struct id *list)
 
 /* Check to make sure the file is an LTO object file.  */
 
+static int
+has_lto_section (void *data, const char *name ATTRIBUTE_UNUSED,
+                off_t offset ATTRIBUTE_UNUSED,
+                off_t length ATTRIBUTE_UNUSED)
+{
+  int *found = (int *) data;
+
+  if (strncmp (name, LTO_SECTION_NAME_PREFIX,
+              sizeof (LTO_SECTION_NAME_PREFIX) - 1) != 0)
+    {
+      if (strncmp (name, OFFLOAD_SECTION_NAME_PREFIX,
+                  sizeof (OFFLOAD_SECTION_NAME_PREFIX) - 1) != 0)
+        return 1;
+    }
+
+  *found = 1;
+
+  /* Stop iteration.  */
+  return 0;
+}
+
 static bool
-maybe_lto_object_file (const char *prog_name)
+is_lto_object_file (const char *prog_name)
 {
-  FILE *f;
-  unsigned char buf[4];
-  int i;
+  const char *errmsg;
+  int err;
+  int found = 0;
+  off_t inoff = 0;
+  int infd = open (prog_name, O_RDONLY | O_BINARY);
 
-  static unsigned char elfmagic[4] = { 0x7f, 'E', 'L', 'F' };
-  static unsigned char coffmagic[2] = { 0x4c, 0x01 };
-  static unsigned char coffmagic_x64[2] = { 0x64, 0x86 };
-  static unsigned char machomagic[4][4] = {
-    { 0xcf, 0xfa, 0xed, 0xfe },
-    { 0xce, 0xfa, 0xed, 0xfe },
-    { 0xfe, 0xed, 0xfa, 0xcf },
-    { 0xfe, 0xed, 0xfa, 0xce }
-  };
+  if (infd == -1)
+    return false;
 
-  f = fopen (prog_name, "rb");
-  if (f == NULL)
+  simple_object_read *inobj = simple_object_start_read (infd, inoff,
+                                                       LTO_SEGMENT_NAME,
+                                                       &errmsg, &err);
+  if (!inobj)
     return false;
-  if (fread (buf, sizeof (buf), 1, f) != 1)
-    buf[0] = 0;
-  fclose (f);
 
-  if (memcmp (buf, elfmagic, sizeof (elfmagic)) == 0
-      || memcmp (buf, coffmagic, sizeof (coffmagic)) == 0
-      || memcmp (buf, coffmagic_x64, sizeof (coffmagic_x64)) == 0)
+  errmsg = simple_object_find_sections (inobj, has_lto_section,
+                                       (void *) &found, &err);
+  if (! errmsg && found)
     return true;
-  for (i = 0; i < 4; i++)
-    if (memcmp (buf, machomagic[i], sizeof (machomagic[i])) == 0)
-      return true;
 
+  if (errmsg)
+    fatal_error (0, "%s: %s\n", errmsg, xstrerror (err));
   return false;
 }
 
@@ -2386,7 +2405,6 @@ scan_prog_file (const char *prog_name, scanpass which_pass,
   int err;
   char *p, buf[1024];
   FILE *inf;
-  int found_lto = 0;
 
   if (which_pass == PASS_SECOND)
     return;
@@ -2394,8 +2412,13 @@ scan_prog_file (const char *prog_name, scanpass which_pass,
   /* LTO objects must be in a known format.  This check prevents
      us from accepting an archive containing LTO objects, which
      gcc cannot currently handle.  */
-  if (which_pass == PASS_LTOINFO && !maybe_lto_object_file (prog_name))
-    return;
+  if (which_pass == PASS_LTOINFO)
+    {
+      if(is_lto_object_file (prog_name)) {
+       add_lto_object (&lto_objects, prog_name);
+      }
+      return;
+    }
 
   /* If we do not have an `nm', complain.  */
   if (nm_file_name == 0)
@@ -2450,12 +2473,7 @@ scan_prog_file (const char *prog_name, scanpass which_pass,
     fatal_error (input_location, "can't open nm output: %m");
 
   if (debug)
-    {
-      if (which_pass == PASS_LTOINFO)
-        fprintf (stderr, "\nnm output with LTO info marker symbol.\n");
-      else
-        fprintf (stderr, "\nnm output with constructors/destructors.\n");
-    }
+    fprintf (stderr, "\nnm output with constructors/destructors.\n");
 
   /* Read each line of nm output.  */
   while (fgets (buf, sizeof buf, inf) != (char *) 0)
@@ -2466,30 +2484,6 @@ scan_prog_file (const char *prog_name, scanpass which_pass,
       if (debug)
         fprintf (stderr, "\t%s\n", buf);
 
-      if (which_pass == PASS_LTOINFO)
-        {
-          if (found_lto)
-            continue;
-
-          /* Look for the LTO info marker symbol, and add filename to
-             the LTO objects list if found.  */
-          for (p = buf; (ch = *p) != '\0' && ch != '\n'; p++)
-            if (ch == ' '  && p[1] == '_' && p[2] == '_'
-               && (strncmp (p + (p[3] == '_' ? 2 : 1), "__gnu_lto_v1", 12) == 0)
-               && ISSPACE (p[p[3] == '_' ? 14 : 13]))
-              {
-                add_lto_object (&lto_objects, prog_name);
-
-                /* We need to read all the input, so we can't just
-                   return here.  But we can avoid useless work.  */
-                found_lto = 1;
-
-                break;
-              }
-
-         continue;
-        }
-
       /* If it contains a constructor or destructor name, add the name
         to the appropriate list unless this is a kind of symbol we're
         not supposed to even consider.  */