Support .gnu.lto_.lto section in ELF files (PR 24768).
authorMartin Liska <mliska@suse.cz>
Thu, 4 Jul 2019 14:39:08 +0000 (16:39 +0200)
committerMartin Liska <mliska@suse.cz>
Mon, 29 Jul 2019 08:11:44 +0000 (10:11 +0200)
bfd/ChangeLog:

2019-07-22  Martin Liska  <mliska@suse.cz>

PR 24768
* archive.c (_bfd_compute_and_write_armap): Come up with
report_plugin_err variable.
* bfd-in2.h (struct bfd): Add lto_slim_object flag.
* elf.c (struct lto_section): New.
(_bfd_elf_make_section_from_shdr): Parse content of
.gnu_lto_.lto section.
* elflink.c: Report error for a missing LTO plugin.
* linker.c (_bfd_generic_link_add_one_symbol): Likewise.

binutils/ChangeLog:

2019-07-22  Martin Liska  <mliska@suse.cz>

PR 24768
* nm.c (filter_symbols): Set report_plugin_err if
error is reported.
(display_rel_file): Report error for a missing LTO plugin.

gold/ChangeLog:

2019-07-22  Martin Liska  <mliska@suse.cz>

PR 24768
* layout.h (class Layout): Add is_lto_slim_object and
set_lto_slim_object.
* object.cc (struct lto_section): Add lto_slim_object_.
(big_endian>::do_layout): Parse content of
.gnu_lto_.lto section.
(big_endian>::do_add_symbols): Report error for a missing
LTO plugin.

bfd/ChangeLog
bfd/archive.c
bfd/bfd-in2.h
bfd/elf.c
bfd/elflink.c
bfd/linker.c
binutils/ChangeLog
binutils/nm.c
gold/ChangeLog
gold/layout.h
gold/object.cc

index 13649040c080a8b6aabe347b29475bba6421c42a..425835179267bdbda021a47be762dab8fd947dd8 100644 (file)
@@ -1,3 +1,15 @@
+2019-07-29  Martin Liska  <mliska@suse.cz>
+
+       PR 24768
+       * archive.c (_bfd_compute_and_write_armap): Come up with
+       report_plugin_err variable.
+       * bfd-in2.h (struct bfd): Add lto_slim_object flag.
+       * elf.c (struct lto_section): New.
+       (_bfd_elf_make_section_from_shdr): Parse content of
+       .gnu_lto_.lto section.
+       * elflink.c: Report error for a missing LTO plugin.
+       * linker.c (_bfd_generic_link_add_one_symbol): Likewise.
+
 2019-07-28  Alan Modra  <amodra@gmail.com>
 
        PR 24857
index 68a92a3e36314959661ae44bfcf6e2cc3bf2fb64..0a7da3a0cb9c839657aa615107abc67d2d103800 100644 (file)
@@ -2236,6 +2236,7 @@ _bfd_compute_and_write_armap (bfd *arch, unsigned int elength)
   long syms_max = 0;
   bfd_boolean ret;
   bfd_size_type amt;
+  static bfd_boolean report_plugin_err = TRUE;
 
   /* Dunno if this is the best place for this info...  */
   if (elength != 0)
@@ -2270,6 +2271,14 @@ _bfd_compute_and_write_armap (bfd *arch, unsigned int elength)
          long symcount;
          long src_count;
 
+         if (current->lto_slim_object && report_plugin_err)
+           {
+             report_plugin_err = FALSE;
+             _bfd_error_handler
+               (_("%pB: plugin needed to handle lto object"),
+                current);
+           }
+
          storage = bfd_get_symtab_upper_bound (current);
          if (storage < 0)
            goto error_return;
@@ -2322,10 +2331,14 @@ _bfd_compute_and_write_armap (bfd *arch, unsigned int elength)
                          && syms[src_count]->name[1] == '_'
                          && strcmp (syms[src_count]->name
                                     + (syms[src_count]->name[2] == '_'),
-                                    "__gnu_lto_slim") == 0)
-                       _bfd_error_handler
-                         (_("%pB: plugin needed to handle lto object"),
-                          current);
+                                    "__gnu_lto_slim") == 0
+                         && report_plugin_err)
+                       {
+                         report_plugin_err = FALSE;
+                         _bfd_error_handler
+                           (_("%pB: plugin needed to handle lto object"),
+                            current);
+                       }
                      namelen = strlen (syms[src_count]->name);
                      amt = sizeof (char *);
                      map[orl_count].name = (char **) bfd_alloc (arch, amt);
index 8374390e60a819bb5fba9ffd35204d9ac0a483eb..7e6dad78d450b3b555bed9a0994d25fcb2d2da01 100644 (file)
@@ -7196,6 +7196,9 @@ struct bfd
   /* Set if this is a plugin output file.  */
   unsigned int lto_output : 1;
 
+  /* Set if this is a slim LTO object not loaded with a compiler plugin.  */
+  unsigned int lto_slim_object: 1;
+
   /* Set to dummy BFD created when claimed by a compiler plug-in
      library.  */
   bfd *plugin_dummy_bfd;
index f47e88b2ac5af875445866452b5b91393f252be2..6b5d12c04433d9705a4ec910958e3153d851262a 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -999,6 +999,18 @@ convert_zdebug_to_debug (bfd *abfd, const char *name)
   return new_name;
 }
 
+/* This a copy of lto_section defined in GCC (lto-streamer.h).  */
+
+struct lto_section
+{
+  int16_t major_version;
+  int16_t minor_version;
+  unsigned char slim_object;
+
+  /* Flags is a private field that is not defined publicly.  */
+  uint16_t flags;
+};
+
 /* Make a BFD section from an ELF section.  We store a pointer to the
    BFD section in the bfd_section field of the header.  */
 
@@ -1275,6 +1287,17 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
        newsect->flags |= SEC_ELF_RENAME;
     }
 
+  /* GCC uses .gnu.lto_.lto.<some_hash> as a LTO bytecode information
+     section.  */
+  const char *lto_section_name = ".gnu.lto_.lto.";
+  if (strncmp (name, lto_section_name, strlen (lto_section_name)) == 0)
+    {
+      struct lto_section lsection;
+      if (bfd_get_section_contents (abfd, newsect, &lsection, 0,
+                                   sizeof (struct lto_section)))
+       abfd->lto_slim_object = lsection.slim_object;
+    }
+
   return TRUE;
 }
 
index ad146d48fc92b073978cff054b80f72adcfb21a8..597184582f345c554e123e19ae7e2778f3da7c5a 100644 (file)
@@ -4401,6 +4401,12 @@ error_free_dyn:
       goto error_free_vers;
     }
 
+  if (abfd->lto_slim_object)
+    {
+      _bfd_error_handler
+       (_("%pB: plugin needed to handle lto object"), abfd);
+    }
+
   for (isym = isymbuf, isymend = isymbuf + extsymcount;
        isym < isymend;
        isym++, sym_hash++, ever = (ever != NULL ? ever + 1 : NULL))
index 1b71fcf8f0d59f0de0363300394425e7ad7ee676..edbd0a7df46901e016f43659ed6b6bdf588c560e 100644 (file)
@@ -1421,12 +1421,24 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
   else if (bfd_is_com_section (section))
     {
       row = COMMON_ROW;
-      if (!bfd_link_relocatable (info)
-         && name[0] == '_'
-         && name[1] == '_'
-         && strcmp (name + (name[2] == '_'), "__gnu_lto_slim") == 0)
-       _bfd_error_handler
-         (_("%pB: plugin needed to handle lto object"), abfd);
+      static bfd_boolean report_plugin_err = TRUE;
+      if (!bfd_link_relocatable (info) && report_plugin_err)
+       {
+         if (abfd->lto_slim_object)
+           {
+             report_plugin_err = FALSE;
+             _bfd_error_handler
+               (_("%pB: plugin needed to handle lto object"), abfd);
+           }
+         else if (name[0] == '_'
+                  && name[1] == '_'
+                  && strcmp (name + (name[2] == '_'), "__gnu_lto_slim") == 0)
+           {
+             report_plugin_err = FALSE;
+             _bfd_error_handler
+               (_("%pB: plugin needed to handle lto object"), abfd);
+           }
+       }
     }
   else
     row = DEF_ROW;
index 9195540282812f70f090755e4755d94b71b4ed1c..f3be2641f15cdcb64ad76f8556d9dbded7d5de1c 100644 (file)
@@ -1,3 +1,10 @@
+2019-07-29  Martin Liska  <mliska@suse.cz>
+
+       PR 24768
+       * nm.c (filter_symbols): Set report_plugin_err if
+       error is reported.
+       (display_rel_file): Report error for a missing LTO plugin.
+
 2019-07-26  Alan Modra  <amodra@gmail.com>
 
        PR 24798
index fd3f73167e085defd041c04e1a3f487ed93c57f0..5d3d647843493a5ad46f00c6b561563243290682 100644 (file)
@@ -438,6 +438,10 @@ print_symdef_entry (bfd *abfd)
     }
 }
 \f
+
+/* True when we can report missing plugin error.  */
+bfd_boolean report_plugin_err = TRUE;
+
 /* Choose which symbol entries to print;
    compact them downward to get rid of the rest.
    Return the number of symbols to be printed.  */
@@ -470,9 +474,13 @@ filter_symbols (bfd *abfd, bfd_boolean is_dynamic, void *minisyms,
 
       if (sym->name[0] == '_'
          && sym->name[1] == '_'
-         && strcmp (sym->name + (sym->name[2] == '_'), "__gnu_lto_slim") == 0)
-       non_fatal (_("%s: plugin needed to handle lto object"),
-                  bfd_get_filename (abfd));
+         && strcmp (sym->name + (sym->name[2] == '_'), "__gnu_lto_slim") == 0
+         && report_plugin_err)
+       {
+         report_plugin_err = FALSE;
+         non_fatal (_("%s: plugin needed to handle lto object"),
+                    bfd_get_filename (abfd));
+       }
 
       if (undefined_only)
        keep = bfd_is_und_section (sym->section);
@@ -1164,6 +1172,15 @@ display_rel_file (bfd *abfd, bfd *archive_bfd)
        }
     }
 
+  /* lto_slim_object is set to false when a bfd is loaded with a compiler
+     LTO plugin.  */
+  if (abfd->lto_slim_object)
+    {
+      report_plugin_err = FALSE;
+      non_fatal (_("%s: plugin needed to handle lto object"),
+                bfd_get_filename (abfd));
+    }
+
   /* Discard the symbols we don't want to print.
      It's OK to do this in place; we'll free the storage anyway
      (after printing).  */
index 67f908885dd94a86185e24e1bfed17bc090a7f52..754d0e3eb202e09f9f0b5993654411a8462bdbf6 100644 (file)
@@ -1,3 +1,14 @@
+2019-07-29  Martin Liska  <mliska@suse.cz>
+
+       PR 24768
+       * layout.h (class Layout): Add is_lto_slim_object and
+       set_lto_slim_object.
+       * object.cc (struct lto_section): Add lto_slim_object_.
+       (big_endian>::do_layout): Parse content of
+       .gnu_lto_.lto section.
+       (big_endian>::do_add_symbols): Report error for a missing
+       LTO plugin.
+
 2019-07-13  Alan Modra  <amodra@gmail.com>
 
        * powerpc.cc (xlate_pcrel_opt): New function.
index bfd44e13077ba201a836f87494fee2bfb9284c6f..b9b75816e8ec0364cf8b51ce33d5048d712a3dfc 100644 (file)
@@ -593,6 +593,14 @@ class Layout
   set_unique_segment_for_sections_specified()
   { this->unique_segment_for_sections_specified_ = true; }
 
+  bool
+  is_lto_slim_object () const
+  { return this->lto_slim_object_; }
+
+  void
+  set_lto_slim_object ()
+  { this->lto_slim_object_ = true; }
+
   // For incremental updates, allocate a block of memory from the
   // free list.  Find a block starting at or after MINOFF.
   off_t
@@ -1480,6 +1488,8 @@ class Layout
   Incremental_inputs* incremental_inputs_;
   // Whether we record output section data created in script
   bool record_output_section_data_from_script_;
+  // Set if this is a slim LTO object not loaded with a compiler plugin
+  bool lto_slim_object_;
   // List of output data that needs to be removed at relaxation clean up.
   Output_section_data_list script_output_section_data_list_;
   // Structure to save segment states before entering the relaxation loop.
index 689448f50c8a784d1142032875203ffc1d28661f..86c519acf72db919ff1f6f2f5540f1514dbf3e10 100644 (file)
@@ -1380,6 +1380,18 @@ Sized_relobj_file<size, big_endian>::layout_gnu_property_section(
     }
 }
 
+// This a copy of lto_section defined in GCC (lto-streamer.h)
+
+struct lto_section
+{
+  int16_t major_version;
+  int16_t minor_version;
+  unsigned char slim_object;
+
+  /* Flags is a private field that is not defined publicly.  */
+  uint16_t flags;
+};
+
 // Lay out the input sections.  We walk through the sections and check
 // whether they should be included in the link.  If they should, we
 // pass them to the Layout object, which will return an output section
@@ -1865,6 +1877,19 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
                debug_types_sections.push_back(i);
            }
        }
+
+      /* GCC uses .gnu.lto_.lto.<some_hash> as a LTO bytecode information
+        section.  */
+      const char *lto_section_name = ".gnu.lto_.lto.";
+      if (strncmp (name, lto_section_name, strlen (lto_section_name)) == 0)
+       {
+         section_size_type contents_len;
+         const unsigned char* pcontents = this->section_contents(i, &contents_len, false);
+         struct lto_section lsection = *(const lto_section*)pcontents;
+         if (lsection.slim_object)
+           gold_info(_("%s: plugin needed to handle lto object"),
+                     this->name().c_str());
+       }
     }
 
   if (!is_pass_two)
@@ -2083,7 +2108,7 @@ template<int size, bool big_endian>
 void
 Sized_relobj_file<size, big_endian>::do_add_symbols(Symbol_table* symtab,
                                                    Read_symbols_data* sd,
-                                                   Layout*)
+                                                   Layout* layout)
 {
   if (sd->symbols == NULL)
     {
@@ -2102,6 +2127,10 @@ Sized_relobj_file<size, big_endian>::do_add_symbols(Symbol_table* symtab,
 
   this->symbols_.resize(symcount);
 
+  if (layout->is_lto_slim_object ())
+    gold_info(_("%s: plugin needed to handle lto object"),
+             this->name().c_str());
+
   const char* sym_names =
     reinterpret_cast<const char*>(sd->symbol_names->data());
   symtab->add_from_relobj(this,