This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Using plugins on mips64*-linux-gnu
- From: Richard Sandiford <rdsandiford at googlemail dot com>
- To: binutils at sourceware dot org
- Cc: dave dot korn dot cygwin at gmail dot com
- Date: Sun, 16 Jan 2011 12:28:22 +0000
- Subject: 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,