This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] ld: Correct private data merging for DSOs
- From: "Maciej W. Rozycki" <macro at codesourcery dot com>
- To: <binutils at sourceware dot org>
- Cc: Richard Sandiford <rdsandiford at googlemail dot com>
- Date: Sat, 1 Dec 2012 23:52:02 +0000
- Subject: [PATCH] ld: Correct private data merging for DSOs
Hi,
We have an issue in the linker with merging private data where dynamic
shared objects are involved. For MIPS targets it affects file header flag
and file attribute ABI compatibility tests that in most, though not all
cases are not made for such objects. Other targets might be affected too;
I encourage the respective maintainters to double-check their code.
There are a few conditions involved, let's examine them one by one, by
input object type and some of its properties:
1. Relocatable object, non-empty input sections present. Such objects are
checked for compatibility with other objects involved in the link. The
condition is bfd_count_sections on the input BFD in lang_check. The
sections are further checked in _bfd_mips_elf_merge_private_bfd_data to
have some contents (with some restrictions) -- this additional check is
only made for file header flags, however for attributes to have any
significant meaning a non-empty .gnu.attributes section must have been
created, so the check would have been redundant. There is no issue for
such objects.
2. Relocatable object, only empty input sections present. These objects
pass the bfd_count_sections check in lang_check and are processed by
_bfd_mips_elf_merge_private_bfd_data. As noted above this implies no
attributes and then for file header flag compatibility tests a
non-empty section would have to be present. In theory one could be
present if created by the linker rather than obtained from input. In
practice I think it does not happen; in particular I believe the
creation of the dynamic sections can never be triggered in the linker
by an input file that only has empty input sections.
3. Relocatable object, no input sections present. These objects are
excluded by the bfd_count_sections condition in lang_check. Like with
files that only have empty input sections, I believe no linker-created
sections can be added.
4. Dynamic shared object, non-empty input sections present. Such objects
are supposed to be checked for compatibility with other objects
involved in the link (there's explicit code in
_bfd_mips_elf_merge_private_bfd_data to handle DSOs and besides I
think we should treat them consistently with relocatable objects).
However for DSOs the section count is reset to zero in
elf_link_add_object_symbols.
Now if this is the first object seen in the link that implies dynamic
sections, they are later on created by the linker and the section count
is increased again. As a result the DSO passes the bfd_count_sections
condition in lang_check and is let through to
_bfd_mips_elf_merge_private_bfd_data. This lets attributes be
verified. The ELF file header compatibility check is made too as the
dynamic sections created will have some contents, although I don't
think they are relevant for ABI compatibility checks.
If dynamic sections have already been created then the DSO is silently
skipped and ABI compatibility checks are not made.
5. Dynamic shared object, only empty or no sections present. In both
cases the section count is set to zero in elf_link_add_object_symbols,
however if such a DSO triggered the creation of dynamic sections, then
it will trigger the ABI compatibility checks in
_bfd_mips_elf_merge_private_bfd_data. Of course that affects file
header flags only as attributes by definition will be absent.
Interestingly enough when the GCC driver is used to link an ordinary
dynamic executable on the MIPS/Linux target (i.e. no special options are
used such as -nostdlib), not even the first DSO is checked for ABI
compatibility as crti.o is always earlier on and will have triggered the
creation of dynamic sections already.
To address these issues I examined a few possible solutions. At first I
was tempted to discard the removal of the old state from
elf_link_add_object_symbols, referred to as "hack" there, and use a flag
as suggested there for a more proper approach, but that has turned out
rather infeasible. Places that interpret the section state are scattered
throughout BFD, including many backends and also non-ELF code. Auditing
all of them at this stage would involve a lot of effort, and cause a risk
of subtle breakage in many places, especially as I can't say I'm confident
all these places would trigger regressions in our test suite. This may
well have been the original reason for this "hack" too.
Therefore I have decided to keep the current approach and look for a
simpler way instead. I thought that before the section state is cleared
in elf_link_add_object_symbols, a copy could be made for places that might
be interested later on in actual input sections only. This turned out to
work quite well and only required a further update to lang_check and
_bfd_mips_elf_merge_private_bfd_data. However eventually I realised this
would be several changes and extra state just to address the case of empty
DSOs, which in reality firstly should not happen in the first place, and
secondly even if they did, then they would generally be examined for file
header flag compatibility by the dynamic linker at the run time regardless
of their lack of actual contents.
Therefore I have finally come up with this simplest solution where all
DSOs are examined unconditionally, which became a one-line change to
generic code in lang_check, and then a further update to
_bfd_mips_elf_merge_private_bfd_data so that empty DSOs (of which there
would be all, due to the hack in elf_link_add_object_symbols) are not
excluded.
Beyond the compatibility checks I have also considered what the effect
might be of the actual attribute merges now, with DSOs in the picture. I
think about the only effect it will have would be a configuration where
executable with no FP ABI specified linked with incompatible shared
libraries, say a hard-float and a soft-float one. Of course such an
executable would be compatible with both and having no FP ABI set would
not pass any FP data around, i.e. the two incompatible FP ABIs would
remain contained to the respective shared libraries. However the first
DSO spotted with an FP ABI set would pass it on to the executable, which
would then reject the other DSO.
I am not sure if such a configuration matters in reality -- if you think
it does, then I'll be happy to consider it in a follow-on patch, however
at this point I suspect it does not. And it is also tricky in practice as
a later relocatable object might indeed have a specific FP ABI set causing
a DSO already accepted incompatible.
In addition to the change described above I made I have decided to
exclude linker-created sections in _bfd_mips_elf_merge_private_bfd_data
explicitly too. Although this probably serves documentation purposes only
as such sections will not have been created for DSOs by the time the input
section state is copied, and as noted above, for relocatable objects (such
as crti.o), other sections will contain data too.
The functionality considered here was not covered by the testsuite,
however the new test cases included here cause the following failures with
our current code as is:
FAIL: MIPS double-float executable with single-float library 3 (o32)
FAIL: MIPS double-float executable with single-float library 4 (o32)
FAIL: MIPS single-float executable with double-float library 3 (o32)
FAIL: MIPS single-float executable with double-float library 4 (o32)
FAIL: MIPS double-float executable with single-float library 3 (n32)
FAIL: MIPS double-float executable with single-float library 4 (n32)
FAIL: MIPS single-float executable with double-float library 3 (n32)
FAIL: MIPS single-float executable with double-float library 4 (n32)
FAIL: MIPS double-float executable with single-float library 3 (n64)
FAIL: MIPS double-float executable with single-float library 4 (n64)
FAIL: MIPS single-float executable with double-float library 3 (n64)
FAIL: MIPS single-float executable with double-float library 4 (n64)
FAIL: MIPS abicalls interlinking non-PIC executable 1 (o32)
FAIL: MIPS abicalls interlinking non-PIC executable 2 (o32)
FAIL: MIPS abicalls interlinking non-PIC executable 1 (n32)
FAIL: MIPS abicalls interlinking non-PIC executable 2 (n32)
FAIL: MIPS abicalls interlinking non-PIC executable 1 (n64)
FAIL: MIPS abicalls interlinking non-PIC executable 2 (n64)
-- that are removed once the fix has been applied. These show how the
order of DSOs matters, the remaining added tests succeed regardless,
providing coverage for the respective execution paths.
A few existing cases had to be adjusted though, as they failed to
complain where non-abicalls relocatables were linked with a DSO -- this
case is commented on in _bfd_mips_elf_merge_private_bfd_data: "DSOs should
only be linked with CPIC code," so I believe that the new complaint is
right and the existing test cases wrong.
I have regression-tested this change over the usual 136 targets with no
problems spotted. Any questions or comments; or otherwise OK to apply?
2012-12-01 Maciej W. Rozycki <macro@codesourcery.com>
bfd/
* elfxx-mips.c (_bfd_mips_elf_merge_private_bfd_data): Always
do file header flag compatibility checks on dynamic shared
objects. Ignore linker-created sections when qualifying
relocatable objects for these checks.
ld/
* ldlang.c (lang_check): Always merge private BFD data of
dynamic shared objects.
ld/testsuite/
* ld-elf/elf.exp: Add -KPIC to ASFLAGS for mips*-*-* and the
pr14170 test.
* ld-elf/export-class.exp: Add -KPIC to ASFLAGS for mips*-*-*.
* ld-mips-elf/export-class.exp (mips_export_class_test): Add
-KPIC to AFLAGS.
* ld-mips-elf/abicalls-lib.s: New test source.
* ld-mips-elf/abicalls.s: New test source.
* ld-mips-elf/abicalls.ll: New test.
* ld-mips-elf/attr-gnu-4-1.gd: New test.
* ld-mips-elf/attr-gnu-4-12.ll: New test.
* ld-mips-elf/attr-gnu-4-2.gd: New test.
* ld-mips-elf/attr-gnu-4-21.ll: New test.
* ld-mips-elf/mips-elf.exp: Run the new tests.
Maciej
binutils-merge-private-sections.diff
Index: binutils-fsf-trunk-quilt/bfd/elfxx-mips.c
===================================================================
--- binutils-fsf-trunk-quilt.orig/bfd/elfxx-mips.c 2012-12-01 11:40:50.000000000 +0000
+++ binutils-fsf-trunk-quilt/bfd/elfxx-mips.c 2012-12-01 12:19:13.341820501 +0000
@@ -13985,7 +13985,6 @@ _bfd_mips_elf_merge_private_bfd_data (bf
flagword old_flags;
flagword new_flags;
bfd_boolean ok;
- bfd_boolean null_input_bfd = TRUE;
asection *sec;
/* Check if we have the same endianness. */
@@ -14057,29 +14056,34 @@ _bfd_mips_elf_merge_private_bfd_data (bf
if (new_flags == old_flags)
return TRUE;
- /* Check to see if the input BFD actually contains any sections.
- If not, its flags may not have been initialised either, but it cannot
- actually cause any incompatibility. */
- for (sec = ibfd->sections; sec != NULL; sec = sec->next)
+ /* For relocatable objects check to see if the input BFD actually contains
+ any sections. If not, its flags may not have been initialised either,
+ but it cannot actually cause any incompatibility. */
+ if (!(ibfd->flags & DYNAMIC))
{
- /* Ignore synthetic sections and empty .text, .data and .bss sections
- 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")
- && strcmp (sec->name, ".data")
- && strcmp (sec->name, ".bss"))))
+ bfd_boolean null_input_bfd = TRUE;
+
+ for (sec = ibfd->sections; sec != NULL; sec = sec->next)
{
- null_input_bfd = FALSE;
- break;
+ /* Ignore synthetic sections and empty .text, .data and .bss
+ sections 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_LINKER_CREATED | SEC_IS_COMMON)) == 0
+ && strcmp (sec->name, ".reginfo")
+ && strcmp (sec->name, ".mdebug")
+ && (sec->size != 0
+ || (strcmp (sec->name, ".text")
+ && strcmp (sec->name, ".data")
+ && strcmp (sec->name, ".bss"))))
+ {
+ null_input_bfd = FALSE;
+ break;
+ }
}
+ if (null_input_bfd)
+ return TRUE;
}
- if (null_input_bfd)
- return TRUE;
ok = TRUE;
Index: binutils-fsf-trunk-quilt/ld/ldlang.c
===================================================================
--- binutils-fsf-trunk-quilt.orig/ld/ldlang.c 2012-12-01 11:40:50.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/ldlang.c 2012-12-01 11:46:48.560697029 +0000
@@ -5930,10 +5930,13 @@ lang_check (void)
bfd_printable_name (input_bfd), input_bfd,
bfd_printable_name (link_info.output_bfd));
}
- else if (bfd_count_sections (input_bfd))
+ else if (bfd_count_sections (input_bfd) || (input_bfd->flags & DYNAMIC))
{
/* If the input bfd has no contents, it shouldn't set the
- private data of the output bfd. */
+ private data of the output bfd. Dynamic objects are always
+ checked as this is what the dynamic linker will generally
+ do too at the run time. The backend still has a choice to
+ skip some checks in that case. */
bfd_error_handler_type pfn = NULL;
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/elf.exp
===================================================================
--- binutils-fsf-trunk-quilt.orig/ld/testsuite/ld-elf/elf.exp 2012-12-01 11:40:50.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/elf.exp 2012-12-01 11:42:04.341781075 +0000
@@ -64,6 +64,10 @@ if { ![istarget hppa64*-hpux*] } {
}
if { [check_shared_lib_support] } then {
+ set old_asflags $ASFLAGS
+ if { [istarget mips*-*-*] } {
+ append ASFLAGS " -KPIC"
+ }
run_ld_link_tests {
{"Build pr14170a.o" "" "" "pr14170a.s" {} "pr14170.a" }
}
@@ -75,6 +79,7 @@ if { ![istarget hppa64*-hpux*] } {
"tmpdir/pr14170a.o tmpdir/pr14170.so" "" "pr14170c.s"
{ } "pr14170" }
}
+ set ASFLAGS $old_asflags
}
}
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/export-class.exp
===================================================================
--- binutils-fsf-trunk-quilt.orig/ld/testsuite/ld-elf/export-class.exp 2012-12-01 11:40:50.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-elf/export-class.exp 2012-12-01 11:42:04.341781075 +0000
@@ -39,6 +39,11 @@ if { ![istarget *-*-linux*]
set testname "Symbol export class test"
+set old_asflags $ASFLAGS
+if { [istarget mips*-*-*] } {
+ append ASFLAGS " -KPIC"
+}
+
# Build an auxiliary shared object with conflicting versioned symbol
# definitions.
run_ld_link_tests [list \
@@ -85,3 +90,5 @@ run_ld_link_tests [list \
"export-class.so" \
] \
]
+
+set ASFLAGS $old_asflags
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-mips-elf/abicalls-lib.s
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-mips-elf/abicalls-lib.s 2012-12-01 11:42:04.341781075 +0000
@@ -0,0 +1,6 @@
+ .data
+ .globl bar
+ .type bar, @object
+bar:
+ .word 0
+ .size bar, . - bar
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-mips-elf/abicalls.ll
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-mips-elf/abicalls.ll 2012-12-01 11:42:04.341781075 +0000
@@ -0,0 +1 @@
+.*: .*: warning: linking abicalls files with non-abicalls files
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-mips-elf/abicalls.s
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-mips-elf/abicalls.s 2012-12-01 11:42:04.341781075 +0000
@@ -0,0 +1,6 @@
+ .data
+ .globl foo
+ .type foo, @object
+foo:
+ .dc.a bar
+ .size foo, . - foo
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-mips-elf/attr-gnu-4-1.gd
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-mips-elf/attr-gnu-4-1.gd 2012-12-01 11:42:04.341781075 +0000
@@ -0,0 +1,4 @@
+Attribute Section: gnu
+File Attributes
+ Tag_GNU_MIPS_ABI_FP: Hard float \(double precision\)
+#pass
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-mips-elf/attr-gnu-4-12.ll
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-mips-elf/attr-gnu-4-12.ll 2012-12-01 11:42:04.341781075 +0000
@@ -0,0 +1 @@
+.*: .* uses -mdouble-float \(set by .*\.o\), .*\.so uses -msingle-float
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-mips-elf/attr-gnu-4-2.gd
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-mips-elf/attr-gnu-4-2.gd 2012-12-01 11:42:04.341781075 +0000
@@ -0,0 +1,4 @@
+Attribute Section: gnu
+File Attributes
+ Tag_GNU_MIPS_ABI_FP: Hard float \(single precision\)
+#pass
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-mips-elf/attr-gnu-4-21.ll
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-mips-elf/attr-gnu-4-21.ll 2012-12-01 11:42:04.341781075 +0000
@@ -0,0 +1 @@
+.*: .* uses -msingle-float \(set by .*\.o\), .*\.so uses -mdouble-float
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-mips-elf/export-class.exp
===================================================================
--- binutils-fsf-trunk-quilt.orig/ld/testsuite/ld-mips-elf/export-class.exp 2012-12-01 11:40:50.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-mips-elf/export-class.exp 2012-12-01 11:42:04.341781075 +0000
@@ -36,7 +36,7 @@ proc mips_export_class_test { abi flag e
set dump [string map {o32 32 n32 32 n64 64} $abi]
- set AFLAGS "$flag -EB"
+ set AFLAGS "$flag -EB -KPIC"
set LDFLAGS "-m$emul"
# Build an auxiliary shared object with conflicting versioned symbol
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-mips-elf/mips-elf.exp
===================================================================
--- binutils-fsf-trunk-quilt.orig/ld/testsuite/ld-mips-elf/mips-elf.exp 2012-12-01 11:40:50.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-mips-elf/mips-elf.exp 2012-12-01 11:42:04.361764845 +0000
@@ -626,6 +626,175 @@ run_dump_test "attr-gnu-4-44"
run_dump_test "attr-gnu-4-45"
run_dump_test "attr-gnu-4-51"
+set abis [concat o32 [expr {$has_newabi ? "n32 n64" : ""}]]
+foreach { abi } $abis {
+ run_ld_link_tests [list \
+ [list \
+ "MIPS double-float relocatable ($abi)" \
+ "$abi_ldflags($abi) -r" \
+ "$abi_asflags($abi) -KPIC" \
+ [list attr-gnu-4-1.s] \
+ [list "readelf -A attr-gnu-4-1.gd"] \
+ "attr-gnu-4-1-${abi}.o"] \
+ [list \
+ "MIPS single-float relocatable ($abi)" \
+ "$abi_ldflags($abi) -r" \
+ "$abi_asflags($abi) -KPIC" \
+ [list attr-gnu-4-2.s] \
+ [list "readelf -A attr-gnu-4-2.gd"] \
+ "attr-gnu-4-2-${abi}.o"] \
+ [list \
+ "MIPS double-float shared library ($abi)" \
+ "$abi_ldflags($abi) -shared tmpdir/attr-gnu-4-1-${abi}.o" \
+ "" \
+ "" \
+ [list "readelf -A attr-gnu-4-1.gd"] \
+ "libattr-gnu-4-1-${abi}.so"] \
+ [list \
+ "MIPS single-float shared library ($abi)" \
+ "$abi_ldflags($abi) -shared tmpdir/attr-gnu-4-2-${abi}.o" \
+ "" \
+ "" \
+ [list "readelf -A attr-gnu-4-2.gd"] \
+ "libattr-gnu-4-2-${abi}.so"] \
+ [list \
+ "MIPS double-float executable 1 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/attr-gnu-4-1-${abi}.o -Ltmpdir -lattr-gnu-4-1-${abi}" \
+ "" \
+ "" \
+ [list "readelf -A attr-gnu-4-1.gd"] \
+ "attr-gnu-4-11-1-${abi}"] \
+ [list \
+ "MIPS double-float executable 2 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/attr-gnu-4-1-${abi}.o tmpdir/libattr-gnu-4-1-${abi}.so" \
+ "" \
+ "" \
+ [list "readelf -A attr-gnu-4-1.gd"] \
+ "attr-gnu-4-11-2-${abi}"] \
+ [list \
+ "MIPS single-float executable 1 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/attr-gnu-4-2-${abi}.o -Ltmpdir -lattr-gnu-4-2-${abi}" \
+ "" \
+ "" \
+ [list "readelf -A attr-gnu-4-2.gd"] \
+ "attr-gnu-4-29-1-${abi}"] \
+ [list \
+ "MIPS single-float executable 2 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/attr-gnu-4-2-${abi}.o tmpdir/libattr-gnu-4-2-${abi}.so" \
+ "" \
+ "" \
+ [list "readelf -A attr-gnu-4-2.gd"] \
+ "attr-gnu-4-29-2-${abi}"] \
+ [list \
+ "MIPS double-float executable with single-float library 1 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/attr-gnu-4-1-${abi}.o -Ltmpdir -lattr-gnu-4-2-${abi}" \
+ "" \
+ "" \
+ [list \
+ "ld attr-gnu-4-12.ll" \
+ "readelf -A attr-gnu-4-1.gd"] \
+ "attr-gnu-4-12-1-${abi}"] \
+ [list \
+ "MIPS double-float executable with single-float library 2 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/attr-gnu-4-1-${abi}.o tmpdir/libattr-gnu-4-2-${abi}.so" \
+ "" \
+ "" \
+ [list \
+ "ld attr-gnu-4-12.ll" \
+ "readelf -A attr-gnu-4-1.gd"] \
+ "attr-gnu-4-12-2-${abi}"] \
+ [list \
+ "MIPS double-float executable with single-float library 3 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/attr-gnu-4-1-${abi}.o -Ltmpdir -lattr-gnu-4-1-${abi} -lattr-gnu-4-2-${abi}" \
+ "" \
+ "" \
+ [list \
+ "ld attr-gnu-4-12.ll" \
+ "readelf -A attr-gnu-4-1.gd"] \
+ "attr-gnu-4-12-1-${abi}"] \
+ [list \
+ "MIPS double-float executable with single-float library 4 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/attr-gnu-4-1-${abi}.o tmpdir/libattr-gnu-4-1-${abi}.so tmpdir/libattr-gnu-4-2-${abi}.so" \
+ "" \
+ "" \
+ [list \
+ "ld attr-gnu-4-12.ll" \
+ "readelf -A attr-gnu-4-1.gd"] \
+ "attr-gnu-4-12-2-${abi}"] \
+ [list \
+ "MIPS double-float executable with single-float library 5 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/attr-gnu-4-1-${abi}.o -Ltmpdir -lattr-gnu-4-2-${abi} -lattr-gnu-4-1-${abi}" \
+ "" \
+ "" \
+ [list \
+ "ld attr-gnu-4-12.ll" \
+ "readelf -A attr-gnu-4-1.gd"] \
+ "attr-gnu-4-12-1-${abi}"] \
+ [list \
+ "MIPS double-float executable with single-float library 6 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/attr-gnu-4-1-${abi}.o tmpdir/libattr-gnu-4-2-${abi}.so tmpdir/libattr-gnu-4-1-${abi}.so" \
+ "" \
+ "" \
+ [list \
+ "ld attr-gnu-4-12.ll" \
+ "readelf -A attr-gnu-4-1.gd"] \
+ "attr-gnu-4-12-2-${abi}"] \
+ [list \
+ "MIPS single-float executable with double-float library 1 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/attr-gnu-4-2-${abi}.o -Ltmpdir -lattr-gnu-4-1-${abi}" \
+ "" \
+ "" \
+ [list \
+ "ld attr-gnu-4-21.ll" \
+ "readelf -A attr-gnu-4-2.gd"] \
+ "attr-gnu-4-21-1-${abi}"] \
+ [list \
+ "MIPS single-float executable with double-float library 2 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/attr-gnu-4-2-${abi}.o tmpdir/libattr-gnu-4-1-${abi}.so" \
+ "" \
+ "" \
+ [list \
+ "ld attr-gnu-4-21.ll" \
+ "readelf -A attr-gnu-4-2.gd"] \
+ "attr-gnu-4-21-2-${abi}"] \
+ [list \
+ "MIPS single-float executable with double-float library 3 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/attr-gnu-4-2-${abi}.o -Ltmpdir -lattr-gnu-4-2-${abi} -lattr-gnu-4-1-${abi}" \
+ "" \
+ "" \
+ [list \
+ "ld attr-gnu-4-21.ll" \
+ "readelf -A attr-gnu-4-2.gd"] \
+ "attr-gnu-4-21-1-${abi}"] \
+ [list \
+ "MIPS single-float executable with double-float library 4 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/attr-gnu-4-2-${abi}.o tmpdir/libattr-gnu-4-2-${abi}.so tmpdir/libattr-gnu-4-1-${abi}.so" \
+ "" \
+ "" \
+ [list \
+ "ld attr-gnu-4-21.ll" \
+ "readelf -A attr-gnu-4-2.gd"] \
+ "attr-gnu-4-21-2-${abi}"] \
+ [list \
+ "MIPS single-float executable with double-float library 5 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/attr-gnu-4-2-${abi}.o -Ltmpdir -lattr-gnu-4-1-${abi} -lattr-gnu-4-2-${abi}" \
+ "" \
+ "" \
+ [list \
+ "ld attr-gnu-4-21.ll" \
+ "readelf -A attr-gnu-4-2.gd"] \
+ "attr-gnu-4-21-1-${abi}"] \
+ [list \
+ "MIPS single-float executable with double-float library 6 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/attr-gnu-4-2-${abi}.o tmpdir/libattr-gnu-4-1-${abi}.so tmpdir/libattr-gnu-4-2-${abi}.so" \
+ "" \
+ "" \
+ [list \
+ "ld attr-gnu-4-21.ll" \
+ "readelf -A attr-gnu-4-2.gd"] \
+ "attr-gnu-4-21-2-${abi}"]]
+}
+
if { $linux_gnu } {
run_ld_link_tests {
{"GOT and versioning 1"
@@ -669,3 +838,121 @@ foreach { abi } $abis {
"readelf -A export-class-call16-${abi}.gd"] \
"export-class-call16-${abi}.so"]]
}
+
+# Non-abicalls shared library interlinking error tests.
+set abis [concat o32 [expr {$has_newabi ? "n32 n64" : ""}]]
+foreach { abi } $abis {
+ run_ld_link_tests [list \
+ [list \
+ "MIPS abicalls interlinking shared library ($abi)" \
+ "$abi_ldflags($abi) -shared" \
+ "$abi_asflags($abi) -KPIC" \
+ [list abicalls-lib.s] \
+ "" \
+ "libabicalls-${abi}.so"] \
+ [list \
+ "MIPS abicalls interlinking PIC relocatable ($abi)" \
+ "$abi_ldflags($abi) -r" \
+ "$abi_asflags($abi) -KPIC" \
+ [list abicalls.s] \
+ "" \
+ "abicalls-pic-${abi}.o"] \
+ [list \
+ "MIPS abicalls interlinking PLT relocatable ($abi)" \
+ "$abi_ldflags($abi) -r" \
+ "$abi_asflags($abi) -call_nonpic" \
+ [list abicalls.s] \
+ "" \
+ "abicalls-plt-${abi}.o"] \
+ [list \
+ "MIPS abicalls interlinking non-PIC relocatable ($abi)" \
+ "$abi_ldflags($abi) -r" \
+ "$abi_asflags($abi)" \
+ [list abicalls.s] \
+ "" \
+ "abicalls-${abi}.o"] \
+ [list \
+ "MIPS abicalls interlinking PIC executable 1 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/abicalls-pic-${abi}.o -Ltmpdir -labicalls-${abi}" \
+ "" \
+ "" \
+ "" \
+ "abicalls-pic-1-${abi}"] \
+ [list \
+ "MIPS abicalls interlinking PIC executable 2 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/abicalls-pic-${abi}.o tmpdir/libabicalls-${abi}.so" \
+ "" \
+ "" \
+ "" \
+ "abicalls-pic-2-${abi}"] \
+ [list \
+ "MIPS abicalls interlinking PIC executable 3 ($abi)" \
+ "$abi_ldflags($abi) -e 0 -Ltmpdir -labicalls-${abi} tmpdir/abicalls-pic-${abi}.o" \
+ "" \
+ "" \
+ "" \
+ "abicalls-pic-3-${abi}"] \
+ [list \
+ "MIPS abicalls interlinking PIC executable 4 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/libabicalls-${abi}.so tmpdir/abicalls-pic-${abi}.o" \
+ "" \
+ "" \
+ "" \
+ "abicalls-pic-4-${abi}"] \
+ [list \
+ "MIPS abicalls interlinking PLT executable 1 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/abicalls-plt-${abi}.o -Ltmpdir -labicalls-${abi}" \
+ "" \
+ "" \
+ "" \
+ "abicalls-plt-1-${abi}"] \
+ [list \
+ "MIPS abicalls interlinking PLT executable 2 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/abicalls-plt-${abi}.o tmpdir/libabicalls-${abi}.so" \
+ "" \
+ "" \
+ "" \
+ "abicalls-plt-2-${abi}"] \
+ [list \
+ "MIPS abicalls interlinking PLT executable 3 ($abi) tmpdir/abicalls-plt-${abi}.o" \
+ "$abi_ldflags($abi) -e 0 -Ltmpdir -labicalls-${abi}" \
+ "" \
+ "" \
+ "" \
+ "abicalls-plt-3-${abi}"] \
+ [list \
+ "MIPS abicalls interlinking PLT executable 4 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/libabicalls-${abi}.so tmpdir/abicalls-plt-${abi}.o" \
+ "" \
+ "" \
+ "" \
+ "abicalls-plt-4-${abi}"] \
+ [list \
+ "MIPS abicalls interlinking non-PIC executable 1 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/abicalls-${abi}.o -Ltmpdir -labicalls-${abi}" \
+ "" \
+ "" \
+ [list "ld abicalls.ll"] \
+ "abicalls-1-${abi}"] \
+ [list \
+ "MIPS abicalls interlinking non-PIC executable 2 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/abicalls-${abi}.o tmpdir/libabicalls-${abi}.so" \
+ "" \
+ "" \
+ [list "ld abicalls.ll"] \
+ "abicalls-2-${abi}"] \
+ [list \
+ "MIPS abicalls interlinking non-PIC executable 3 ($abi)" \
+ "$abi_ldflags($abi) -e 0 -Ltmpdir -labicalls-${abi} tmpdir/abicalls-${abi}.o" \
+ "" \
+ "" \
+ [list "ld abicalls.ll"] \
+ "abicalls-3-${abi}"] \
+ [list \
+ "MIPS abicalls interlinking non-PIC executable 4 ($abi)" \
+ "$abi_ldflags($abi) -e 0 tmpdir/libabicalls-${abi}.so tmpdir/abicalls-${abi}.o" \
+ "" \
+ "" \
+ [list "ld abicalls.ll"] \
+ "abicalls-4-${abi}"]]
+}