This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH, MIPS] When calculating a relocation using an undefined weak symbol don't check for overflow.
- From: Andrew Bennett <Andrew dot Bennett at imgtec dot com>
- To: "binutils at sourceware dot org" <binutils at sourceware dot org>
- Cc: "rdsandiford at googlemail dot com" <rdsandiford at googlemail dot com>
- Date: Fri, 21 Nov 2014 13:14:15 +0000
- Subject: [PATCH, MIPS] When calculating a relocation using an undefined weak symbol don't check for overflow.
- Authentication-results: sourceware.org; auth=none
Hi,
In MIPS the relocation calculation only ignores the overflow checks for undefined
weak symbols on relocations associated with j/jal. This patch extends this to
the relocations used by the: b* instructions; pc/gp relative symbol offsets; and the
lwpc/ldpc MIPS r6 instructions.
I have added a new test into the linker testsuite, and both the gas and ld
testsuites successfully pass with my patch.
On a side note I noticed that for the R_MIPS_26 relocation the overflow check is
only performed for global non undefined weak symbols. I was wondering why it is not
done for local symbols?
The ChangeLog and patch are below.
Ok to commit?
Many thanks,
Andrew
bfd/
* elfxx-mips.c (mips_elf_calculate_relocation): Only check for overflow
on non-weak undefined symbols.
ld/testsuite/
* ld-mips-elf/mips-elf.exp: Add in undefined weak overflow tests for
o32, n32 and n64.
* ld-mips-elf/undefweak-overflow.s: New test.
* ld-mips-elf/undefweak-overflow.d: New test.
* ld-mips-elf/undefweak-overflow-n64.d: New test.
* ld-mips-elf/undefweak-overflow-n64.d: New test.
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index 8664c18..4cf4ac0 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -5928,7 +5928,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
to them before. */
if (was_local_p)
value += gp0;
- overflowed_p = mips_elf_overflow_p (value, 16);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 16);
break;
case R_MIPS16_GOT16:
@@ -5983,7 +5984,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
return bfd_reloc_outofrange;
value = symbol + addend - p;
- overflowed_p = mips_elf_overflow_p (value, 18);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 18);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
@@ -5996,7 +5998,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
return bfd_reloc_outofrange;
value = symbol + addend - p;
- overflowed_p = mips_elf_overflow_p (value, 23);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 23);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
@@ -6009,7 +6012,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
return bfd_reloc_outofrange;
value = symbol + addend - p;
- overflowed_p = mips_elf_overflow_p (value, 28);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 28);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
@@ -6022,7 +6026,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
return bfd_reloc_outofrange;
value = symbol + addend - ((p | 7) ^ 7);
- overflowed_p = mips_elf_overflow_p (value, 21);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 21);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
@@ -6035,14 +6040,16 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
return bfd_reloc_outofrange;
value = symbol + addend - p;
- overflowed_p = mips_elf_overflow_p (value, 21);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 21);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
case R_MIPS_PCHI16:
value = mips_elf_high (symbol + addend - p);
- overflowed_p = mips_elf_overflow_p (value, 16);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 16);
value &= howto->dst_mask;
break;
@@ -6057,7 +6064,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
if (howto->partial_inplace)
addend = _bfd_mips_elf_sign_extend (addend, 8);
value = symbol + addend - p;
- overflowed_p = mips_elf_overflow_p (value, 8);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 8);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
@@ -6066,7 +6074,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
if (howto->partial_inplace)
addend = _bfd_mips_elf_sign_extend (addend, 11);
value = symbol + addend - p;
- overflowed_p = mips_elf_overflow_p (value, 11);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 11);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
@@ -6075,7 +6084,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
if (howto->partial_inplace)
addend = _bfd_mips_elf_sign_extend (addend, 17);
value = symbol + addend - p;
- overflowed_p = mips_elf_overflow_p (value, 17);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 17);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
@@ -6084,7 +6094,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
if (howto->partial_inplace)
addend = _bfd_mips_elf_sign_extend (addend, 25);
value = symbol + addend - ((p | 3) ^ 3);
- overflowed_p = mips_elf_overflow_p (value, 25);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 25);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
diff --git a/ld/testsuite/ld-mips-elf/mips-elf.exp b/ld/testsuite/ld-mips-elf/mips-elf.exp
index 91036de..21c809f 100644
--- a/ld/testsuite/ld-mips-elf/mips-elf.exp
+++ b/ld/testsuite/ld-mips-elf/mips-elf.exp
@@ -434,6 +434,13 @@ if {$linux_gnu} {
run_dump_test "jaloverflow"
run_dump_test "jaloverflow-2"
+run_dump_test "undefweak-overflow"
+
+if {$has_newabi} {
+ run_dump_test "undefweak-overflow-n32"
+ run_dump_test "undefweak-overflow-n64"
+}
+
if {$has_newabi} {
run_dump_test "jalbal" [list [list ld $abi_ldflags(n32)]]
}
diff --git a/ld/testsuite/ld-mips-elf/undefweak-overflow-n32.d b/ld/testsuite/ld-mips-elf/undefweak-overflow-n32.d
new file mode 100644
index 0000000..4d965b8
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/undefweak-overflow-n32.d
@@ -0,0 +1,23 @@
+#name: undefined weak symbol overflow (n32)
+#source: undefweak-overflow.s
+#as: -n32 -EB
+#ld: -melf32btsmipn32 -Ttext=0x20000000 -e start
+#objdump: -dr
+#...
+0*20000000: d85fffff.*
+0*20000004: 00000000.*
+0*20000008: f85ffffd.*
+0*2000000c: ec4ffffd.*
+0*20000010: ec5bfffe.*
+0*20000014: cbfffffa.*
+0*20000018: 3c04e000.*
+0*2000001c: 1000fff8.*
+0*20000020: 2484ffe0.*
+0*20000024: 0411fff6.*
+0*20000028: 00000000.*
+0*2000002c: 3c047fd0.*
+0*20000030: 8e670c00.*
+0*20000034: cfe50c00.*
+0*20000038: 9400ffe2.*
+0*2000003c: 0c000c00.*
+#pass
diff --git a/ld/testsuite/ld-mips-elf/undefweak-overflow-n64.d b/ld/testsuite/ld-mips-elf/undefweak-overflow-n64.d
new file mode 100644
index 0000000..e0d9fda
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/undefweak-overflow-n64.d
@@ -0,0 +1,23 @@
+#name: undefined weak symbol overflow (n64)
+#source: undefweak-overflow.s
+#as: -64 -EB
+#ld: -melf64btsmip -Ttext=0x20000000 -e start
+#objdump: -dr
+#...
+ 0*20000000: d85fffff.*
+ 0*20000004: 00000000.*
+ 0*20000008: f85ffffd.*
+ 0*2000000c: ec4ffffd.*
+ 0*20000010: ec5bfffe.*
+ 0*20000014: cbfffffa.*
+ 0*20000018: 3c04e000.*
+ 0*2000001c: 1000fff8.*
+ 0*20000020: 2484ffe0.*
+ 0*20000024: 0411fff6.*
+ 0*20000028: 00000000.*
+ 0*2000002c: 3c047fd0.*
+ 0*20000030: 8e670c00.*
+ 0*20000034: cfe50c00.*
+ 0*20000038: 9400ffe2.*
+ 0*2000003c: 0c000c00.*
+#pass
diff --git a/ld/testsuite/ld-mips-elf/undefweak-overflow.d b/ld/testsuite/ld-mips-elf/undefweak-overflow.d
new file mode 100644
index 0000000..18b3a90
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/undefweak-overflow.d
@@ -0,0 +1,23 @@
+#name: undefined weak symbol overflow
+#source: undefweak-overflow.s
+#as: -32 -EB
+#ld: -melf32btsmip -Ttext=0x20000000 -e start
+#objdump: -dr
+#...
+0*20000000: d85fffff.*
+0*20000004: 00000000.*
+0*20000008: f85ffffd.*
+0*2000000c: ec4ffffd.*
+0*20000010: ec5bfffe.*
+0*20000014: cbfffffa.*
+0*20000018: 3c04e000.*
+0*2000001c: 1000fff8.*
+0*20000020: 2484ffe0.*
+0*20000024: 0411fff6.*
+0*20000028: 00000000.*
+0*2000002c: 3c047fd0.*
+0*20000030: 8e670c00.*
+0*20000034: cfe50c00.*
+0*20000038: 9400ffe2.*
+0*2000003c: 0c000c00.*
+#pass
diff --git a/ld/testsuite/ld-mips-elf/undefweak-overflow.s b/ld/testsuite/ld-mips-elf/undefweak-overflow.s
new file mode 100644
index 0000000..525f11b
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/undefweak-overflow.s
@@ -0,0 +1,25 @@
+# relocs against undefined weak symbols should not be treated as
+# overflowing
+
+
+ .globl start
+ .weak foo
+start:
+ .set mips64r6
+ beqzc $2, foo
+ bnezc $2, foo
+ lwpc $2, foo
+ ldpc $2, foo
+ bc foo
+ lui $4, %pcrel_hi(foo)
+ addiu $4, $4, %pcrel_lo(foo)
+
+ .set mips32r2
+ b foo
+ bal foo
+ lui $4, %gp_rel(foo)
+
+ .set micromips
+ beqz16 $4, foo
+ b16 foo
+ b foo