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]

Using plugins on mips64*-linux-gnu


Now that -fuse-linker-plugin is the default, I realise that plugins
don't work on mips64*-linux-gnu.  Trying to link an n32 binary gives
errors like:

mips64-linux-gnu-ld: /tmp/ccKklblg.o.ironly: ABI is incompatible with that of the selected emulation
mips64-linux-gnu-ld: failed to merge target specific data of file /tmp/ccKklblg.o.ironly
collect2: ld returned 1 exit status

The target vector of the ironly bfd (elf32-tradbigmips) isn't the same
as the target vector of the output (elf32-ntradbigmips).

When creating the ironly bfd, we copy its target vector from the
original input bfd, which is indeed elf32-ntradbigmips.  However,
when making the bfd readable, we recompute the target vector from the
file contents.  The ELF flags have a bit to distinguish between o32
(elf32-tradbigmips) and n32 (elf32-ntradbigmips), and since this bit
isn't set, we end up picking the wrong one.

Now it could be argued that elf32-ntradbigmips should set the n32 bit
when writing out the file, rather than leaving it to the bfd user.
However, that wouldn't be a complete fix.  Each MIPS target vector
represents several sub-ABIs, and if we don't copy the ELF flags across,
we could end up with an incompatibility between objects that use the
same vector.  For example, n32, n64 and o32 all have link-incompatible
"abicalls" and "no-abicalls" variants, hard- and soft-float variants,
and so on.  Regardless of whether we do the compatibility check for
ironly files, it feels wrong to have a different ABI in the link list.
I think we should instead copy the private bfd data across to the
ironly bfd.

There's a related problem.  MIPS distinguishes between "normal common"
and "small common", and when you add a common symbol, the backend
uses the GP size to choose between them.  The default GP size is 8,
but the usual GP size for GNU/Linux objects is 0.  As things stand,
the ironly object ends up with a GP size of 8, so some plugin-defined
common symbols are unnecessarily defined as small common, eating up
valuable GP-relative room.  I think we should copy the GP size across
to the ironly bfd as well.

Defining small common symbols showed up a further bug.  We'd normally
(and rightly) skip the bfd_merge_private_bfd_data step for ironly objects,
because they wouldn't have any non-empty sections.  However, the MIPS
backend defines small common symbols using a fake .scommon section,
and the size of that section reflects all the symbols that has been
defined in it.  This means that we _do_ invoke bfd_merge_private_bfd_data
if a small common symbol is defined.  Without the bfd_copy_private_bfd_data
change above, this leads to errors like:

mips64-linux-gnu-ld: /tmp/cciojNhy.o.ironly: warning: linking abicalls files with non-abicalls files
mips64-linux-gnu-ld: /tmp/cciojNhy.o.ironly: linking 32-bit code with 64-bit code

when linking with "-mabi=32".  The MIPS backend should check for common
sections when deciding whether an input bfd is empty.

Patch tested on mips64-linux-gnu.  Dave, does it look OK to you?

Richard


bfd/
	* elfxx-mips.c (_bfd_mips_elf_merge_private_bfd_data): Ignore
	common sections too.

ld/
	* plugin.c (plugin_get_ir_dummy_bfd): Copy across the bfd's
	private data and GP size.

Index: bfd/elfxx-mips.c
===================================================================
--- bfd/elfxx-mips.c	2011-01-16 12:02:35.000000000 +0000
+++ bfd/elfxx-mips.c	2011-01-16 12:23:14.000000000 +0000
@@ -12597,8 +12597,11 @@ _bfd_mips_elf_merge_private_bfd_data (bf
   for (sec = ibfd->sections; sec != NULL; sec = sec->next)
     {
       /* Ignore synthetic sections and empty .text, .data and .bss sections
-	  which are automatically generated by gas.  */
-      if (strcmp (sec->name, ".reginfo")
+	 which are automatically generated by gas.  Also ignore fake
+	 (s)common sections, since merely defining a common symbol does
+	 not affect compatibility.  */
+      if ((sec->flags & SEC_IS_COMMON) == 0
+	  && strcmp (sec->name, ".reginfo")
 	  && strcmp (sec->name, ".mdebug")
 	  && (sec->size != 0
 	      || (strcmp (sec->name, ".text")
Index: ld/plugin.c
===================================================================
--- ld/plugin.c	2011-01-16 12:02:27.000000000 +0000
+++ ld/plugin.c	2011-01-16 12:06:54.000000000 +0000
@@ -237,6 +237,8 @@ plugin_get_ir_dummy_bfd (const char *nam
 		     srctemplate);
   bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate));
   bfd_make_writable (abfd);
+  bfd_copy_private_bfd_data (srctemplate, abfd);
+  bfd_set_gp_size (abfd, bfd_get_gp_size (abfd));
   /* Create a minimal set of sections to own the symbols.  */
   sec = bfd_make_section_old_way (abfd, ".text");
   bfd_set_section_flags (abfd, sec,


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