This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] GAS: .reloc: Avoid lost addend in converted relocs
- From: "Maciej W. Rozycki" <macro at codesourcery dot com>
- To: <binutils at sourceware dot org>
- Cc: Alan Modra <amodra at gmail dot com>, Richard Sandiford <rdsandiford at googlemail dot com>
- Date: Tue, 28 May 2013 17:39:04 +0100
- Subject: [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}"]]
+}