This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Support .gnu.lto_.lto section in ELF files (PR 24768).


Hi.

The patch adds detection of a new LTO ELF section that will eventually
replace presence of the __gnu_lto_slim symbol detection. So, first I would
like to teach binutils about the section and later then (after some years),
detection based on __gnu_lto_slim symbol can be removed.

Ready for trunk?
Thanks,
Martin

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/archive.c  | 21 +++++++++++++++++----
 bfd/bfd-in2.h  |  3 +++
 bfd/elf.c      | 23 +++++++++++++++++++++++
 bfd/elflink.c  |  6 ++++++
 bfd/linker.c   | 24 ++++++++++++++++++------
 binutils/nm.c  | 23 ++++++++++++++++++++---
 gold/layout.h  | 10 ++++++++++
 gold/object.cc | 31 ++++++++++++++++++++++++++++++-
 8 files changed, 127 insertions(+), 14 deletions(-)


diff --git a/bfd/archive.c b/bfd/archive.c
index 68a92a3e36..0a7da3a0cb 100644
--- a/bfd/archive.c
+++ b/bfd/archive.c
@@ -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);
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 8374390e60..7e6dad78d4 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -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;
diff --git a/bfd/elf.c b/bfd/elf.c
index 265150d511..bb35db54ed 100644
--- 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.  */
 
@@ -1262,6 +1274,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;
 }
 
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 9175d3fa20..1c5eae143a 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -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))
diff --git a/bfd/linker.c b/bfd/linker.c
index 1b71fcf8f0..edbd0a7df4 100644
--- a/bfd/linker.c
+++ b/bfd/linker.c
@@ -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;
diff --git a/binutils/nm.c b/binutils/nm.c
index fd3f73167e..5d3d647843 100644
--- a/binutils/nm.c
+++ b/binutils/nm.c
@@ -438,6 +438,10 @@ print_symdef_entry (bfd *abfd)
     }
 }
 
+
+/* 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).  */
diff --git a/gold/layout.h b/gold/layout.h
index bfd44e1307..b9b75816e8 100644
--- a/gold/layout.h
+++ b/gold/layout.h
@@ -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.
diff --git a/gold/object.cc b/gold/object.cc
index 689448f50c..86c519acf7 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -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,


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]