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, MIPS] When calculating a relocation using an undefined weak symbol don't check for overflow.


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



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