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] GAS: .reloc: Avoid lost addend in converted relocs


Hi,

 We have a problem with the .reloc pseudo-op on REL targets where the 
symbol referred is local and the reloc requested has no room for the 
addend.  We convert the reloc to refer to the corresponding section symbol 
with an addend, but given the lack of room we lose the addend and refer to 
section symbol itself instead.

 It was seen with the R_MIPS_JALR optimisation hint relocation, used by LD 
to convert a register jump to an immediate branch for performance (branch 
prediction) purposes in PIC code.  As a result code corruption happens as 
the branch directs control to the start of the section rather than the 
intended place.  This is illustrated with the test case included with the 
fix below.

 It has turned out to be another corner case in the generic .reloc 
handling code.  I propose the change below, that handles both the case of 
R_MIPS_JALR seen here and tightens the conditions I previously used to 
check for PC-relative relocations whose intermediate addend can overflow 
even if the final one is not going to, by referring to the section's 
use_rela_p flag explicitly rather than relying solely on the 
partial_inplace flag that can be clear even on REL targets, such as with 
R_MIPS_JALR.

 No regressions across the usual 139 targets.  OK to install?

2013-05-28  Maciej W. Rozycki  <macro@codesourcery.com>

	gas/
	* write.c (resolve_reloc_expr_symbols): On REL targets don't
	convert relocs who have no relocatable field either.  Rephrase
	the conditional so that the PC-relative check is only applied
	for REL targets.

	gas/testsuite/
	* gas/mips/jalr3.d: New test.
	* gas/mips/jalr3-n32.d: New test.
	* gas/mips/jalr3-n64.d: New test.
	* gas/mips/jalr3.s: New test source.
	* gas/mips/mips.exp: Run the new tests.

	ld/testsuite/
	* ld-mips-elf/jalr3.dd: New test.
	* ld-mips-elf/jalr3.ld: New test linker script.
	* ld-mips-elf/mips-elf.exp: Run the new test.

  Maciej

binutils-mips-gas-reloc-convert.diff
Index: binutils-fsf-trunk-quilt/gas/testsuite/gas/mips/jalr3-n32.d
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/gas/testsuite/gas/mips/jalr3-n32.d	2013-05-24 21:32:47.043212725 +0100
@@ -0,0 +1,5 @@
+#objdump: -r -j .text
+#name: MIPS JALR reloc (n32)
+#as: -n32
+#source: jalr3.s
+#dump: jalr3.d
Index: binutils-fsf-trunk-quilt/gas/testsuite/gas/mips/jalr3-n64.d
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/gas/testsuite/gas/mips/jalr3-n64.d	2013-05-24 21:32:47.043212725 +0100
@@ -0,0 +1,15 @@
+#objdump: -r -j .text
+#name: MIPS JALR reloc (n64)
+#as: -64
+#source: jalr3.s
+
+.*: +file format .*mips.*
+
+RELOCATION RECORDS FOR \[\.text\]:
+OFFSET           TYPE              VALUE 
+0000000000000000 R_MIPS_JALR       \$bar
+0000000000000000 R_MIPS_NONE       \*ABS\*
+0000000000000000 R_MIPS_NONE       \*ABS\*
+0000000000000008 R_MIPS_JALR       \$bar
+0000000000000008 R_MIPS_NONE       \*ABS\*
+0000000000000008 R_MIPS_NONE       \*ABS\*
Index: binutils-fsf-trunk-quilt/gas/testsuite/gas/mips/jalr3.d
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/gas/testsuite/gas/mips/jalr3.d	2013-05-24 21:32:47.043212725 +0100
@@ -0,0 +1,11 @@
+#objdump: -r -j .text
+#name: MIPS JALR reloc (o32)
+#as: -32
+#source: jalr3.s
+
+.*: +file format .*mips.*
+
+RELOCATION RECORDS FOR \[\.text\]:
+OFFSET   TYPE              VALUE 
+00000000 R_MIPS_JALR       \$bar
+00000008 R_MIPS_JALR       \$bar
Index: binutils-fsf-trunk-quilt/gas/testsuite/gas/mips/jalr3.s
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/gas/testsuite/gas/mips/jalr3.s	2013-05-24 21:32:47.043212725 +0100
@@ -0,0 +1,21 @@
+	.text
+
+	.set	$bar, bar
+
+	.globl	foo
+	.ent	foo
+foo:
+	.reloc	1f, R_MIPS_JALR, $bar
+1:	jalr	$25
+	.reloc	1f, R_MIPS_JALR, $bar
+1:	jr	$25
+	.end	foo
+
+	.ent	bar
+bar:
+	j	$31
+	.end	bar
+
+# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
+	.align	4, 0
+	.space	16
Index: binutils-fsf-trunk-quilt/gas/testsuite/gas/mips/mips.exp
===================================================================
--- binutils-fsf-trunk-quilt.orig/gas/testsuite/gas/mips/mips.exp	2013-05-24 20:49:25.000000000 +0100
+++ binutils-fsf-trunk-quilt/gas/testsuite/gas/mips/mips.exp	2013-05-26 13:50:08.153587530 +0100
@@ -969,6 +969,16 @@ if { [istarget mips*-*-vxworks*] } {
 	run_dump_test "tls-o32"
 	run_dump_test "tls-relw"
 	run_dump_test "jalr2"
+	run_dump_test_arches "jalr3"	[mips_arch_list_matching mips1 \
+					    !micromips]
+	if $has_newabi {
+	    run_dump_test_arches "jalr3-n32" \
+					[mips_arch_list_matching mips3 \
+					    !micromips]
+	    run_dump_test_arches "jalr3-n64" \
+					[mips_arch_list_matching mips3 \
+					    !micromips]
+	}
 
 	run_dump_test_arches "aent"	[mips_arch_list_matching mips1]
 
Index: binutils-fsf-trunk-quilt/gas/write.c
===================================================================
--- binutils-fsf-trunk-quilt.orig/gas/write.c	2013-05-24 20:43:21.000000000 +0100
+++ binutils-fsf-trunk-quilt/gas/write.c	2013-05-28 14:57:59.333801491 +0100
@@ -722,9 +722,10 @@ resolve_reloc_expr_symbols (void)
 	         unless it has enough bits to cover the whole address
 	         space.  */
 	      if (S_IS_LOCAL (sym) && !symbol_section_p (sym)
-		  && !(howto->partial_inplace
-		       && howto->pc_relative
-		       && howto->src_mask != addr_mask))
+		  && (sec->use_rela_p
+		      || (howto->partial_inplace
+			  && (!howto->pc_relative
+			      || howto->src_mask == addr_mask))))
 		{
 		  asection *symsec = S_GET_SEGMENT (sym);
 		  if (!(((symsec->flags & SEC_MERGE) != 0
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-mips-elf/jalr3.dd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-mips-elf/jalr3.dd	2013-05-24 21:32:47.043212725 +0100
@@ -0,0 +1,14 @@
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+
+0+000000 <foo>:
+   0:	04110003 	bal	10 <\$bar>
+   4:	00000000 	nop
+   8:	10000001 	b	10 <\$bar>
+   c:	00000000 	nop
+
+0+000010 <\$bar>:
+  10:	03e00008 	jr	ra
+  14:	00000000 	nop
+	\.\.\.
Index: binutils-fsf-trunk-quilt/ld/testsuite/ld-mips-elf/jalr3.ld
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-mips-elf/jalr3.ld	2013-05-24 21:32:47.043212725 +0100
@@ -0,0 +1,5 @@
+ENTRY(foo)
+SECTIONS
+{
+  .text : { *(.text) }
+}
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	2013-05-24 20:43:21.000000000 +0100
+++ binutils-fsf-trunk-quilt/ld/testsuite/ld-mips-elf/mips-elf.exp	2013-05-24 21:32:47.043212725 +0100
@@ -734,3 +734,16 @@ foreach { abi } $abis {
             [list "readelf -s ehdr_start-2.nd"] \
             "ehdr_start-2-${abi}"]]
 }
+
+# R_MIPS_JALR reloc tests.
+set abis [concat o32 [expr {$has_newabi ? "n32 n64" : ""}]]
+foreach { abi } $abis {
+    run_ld_link_tests [list \
+	[list \
+	    "MIPS JALR reloc test ($abi)" \
+	    "$abi_ldflags($abi) -T jalr3.ld" "" \
+	    "$abi_asflags($abi)" \
+	    [list ../../../gas/testsuite/gas/mips/jalr3.s] \
+	    [list "objdump -d jalr3.dd"] \
+	    "jalr3-${abi}"]]
+}


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