This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[8/21] bfd_install_relocation strikes again
- From: Richard Sandiford <richards at transitive dot com>
- To: binutils at sourceware dot org
- Date: Tue, 10 Mar 2009 14:14:51 +0000
- Subject: [8/21] bfd_install_relocation strikes again
- References: <g4y6vd7a4x.fsf@richards-desktop.transitives.com>
The !OBJ_ELF part of tc-ppc.c:md_apply_fix says:
/* FIXME FIXME FIXME: The value we are passed in *valP includes
the symbol values. If we are doing this relocation the code in
write.c is going to call bfd_install_relocation, which is also
going to use the symbol value. That means that if the reloc is
fully resolved we want to use *valP since bfd_install_relocation is
not being used.
However, if the reloc is not fully resolved we do not want to use
*valP, and must use fx_offset instead. However, if the reloc
is PC relative, we do want to use *valP since it includes the
result of md_pcrel_from. This is confusing. */
if (fixP->fx_addsy == (symbolS *) NULL)
fixP->fx_done = 1;
else if (fixP->fx_pcrel)
;
else
value = fixP->fx_offset;
But the "double symbol" problem described here applies to PC-relative
relocs just as much as it does to other relocs. E.g. if we have:
bar: bl foo
...
foo:
the relocation field is set to:
(foo - .text) * 2 - (bar - .text)
rather than the intended:
(foo - .text) - (bar - .text)
So we should still recompute VALUE for PC_relative relocs, but re-apply
md_pcrel_from_section to the result.
OK to install?
Richard
gas/
* config/tc-ppc.c (md_apply_fix): On COFF targets, always reread
"value" from fx_offset. Manually resubtract md_pcrel_from_section
where necessary.
gas/testsuite/
* gas/ppc/xcoff-branch-1.s, gas/ppc/xcoff-branch-1-32.d,
gas/ppc/xcoff-branch-1-64.d: New tests.
* gas/ppc/aix.exp: Run them.
Index: gas/config/tc-ppc.c
===================================================================
--- gas/config/tc-ppc.c 2009-03-10 13:38:53.000000000 +0000
+++ gas/config/tc-ppc.c 2009-03-10 13:46:12.000000000 +0000
@@ -5617,18 +5617,19 @@ md_apply_fix (fixS *fixP, valueT *valP,
going to use the symbol value. That means that if the reloc is
fully resolved we want to use *valP since bfd_install_relocation is
not being used.
- However, if the reloc is not fully resolved we do not want to use
- *valP, and must use fx_offset instead. However, if the reloc
- is PC relative, we do want to use *valP since it includes the
- result of md_pcrel_from. This is confusing. */
+ However, if the reloc is not fully resolved we do not want to
+ use *valP, and must use fx_offset instead. If the relocation
+ is PC-relative, we then need to re-apply md_pcrel_from_section
+ to this new relocation value. */
if (fixP->fx_addsy == (symbolS *) NULL)
fixP->fx_done = 1;
- else if (fixP->fx_pcrel)
- ;
-
else
- value = fixP->fx_offset;
+ {
+ value = fixP->fx_offset;
+ if (fixP->fx_pcrel)
+ value -= md_pcrel_from_section (fixP, seg);
+ }
#endif
if (fixP->fx_subsy != (symbolS *) NULL)
Index: gas/testsuite/gas/ppc/xcoff-branch-1.s
===================================================================
--- /dev/null 2009-02-06 09:11:03.343159000 +0000
+++ gas/testsuite/gas/ppc/xcoff-branch-1.s 2009-03-10 13:46:12.000000000 +0000
@@ -0,0 +1,40 @@
+ .globl .foo
+ .globl foo1
+ .globl foo2
+ .globl .bar
+ .globl .frob
+
+ .csect .foo[PR]
+.foo:
+ bl foo2 + 0x4
+ bl foo1 + 0xc
+ bl foo1
+ bl foo2
+ bl .bar
+foo1:
+ bl .foo
+ bl .frob
+ bl .foo + 0x10
+ bl .bar + 0x8
+foo2:
+ bl .frob + 0x10
+ blr
+
+ .csect .bar[PR]
+.bar: bl foo1
+ bl foo2
+ bl foo1 + 0x8
+ bl foo2 + 0x4
+ bl .foo
+ bl .bar
+ bl .frob
+ bl .foo + 0x1c
+ bl .bar + 0xc
+ bl .frob + 0x4
+
+ .csect .frob[PR]
+.frob: bl .foo
+ bl .bar
+ bl .frob
+ bl foo1
+ bl foo2
Index: gas/testsuite/gas/ppc/xcoff-branch-1-32.d
===================================================================
--- /dev/null 2009-02-06 09:11:03.343159000 +0000
+++ gas/testsuite/gas/ppc/xcoff-branch-1-32.d 2009-03-10 13:46:12.000000000 +0000
@@ -0,0 +1,61 @@
+#as: -a32
+#source: xcoff-branch-1.s
+#objdump: -dr
+#name: XCOFF branch test 1 (32-bit)
+
+.*
+
+
+Disassembly of section \.text:
+
+0+00 <\.foo>:
+ 0: 48 00 00 29 bl 28 <foo2\+0x4>
+ 4: 48 00 00 1d bl 20 <foo1\+0xc>
+ 8: 48 00 00 0d bl 14 <foo1>
+ c: 48 00 00 19 bl 24 <foo2>
+ 10: 48 00 00 1d bl 2c <\.bar>
+ 10: R_(RBR_26|BR) .*
+
+0+14 <foo1>:
+ 14: 4b ff ff ed bl 0 <\.foo>
+ 18: 48 00 00 3d bl 54 <\.frob>
+ 18: R_(RBR_26|BR) .*
+ 1c: 4b ff ff f5 bl 10 <\.foo\+0x10>
+ 20: 48 00 00 15 bl 34 <\.bar\+0x8>
+ 20: R_(RBR_26|BR) .*
+
+0+24 <foo2>:
+ 24: 48 00 00 41 bl 64 <\.frob\+0x10>
+ 24: R_(RBR_26|BR) .*
+ 28: 4e 80 00 20 br
+
+0+2c <\.bar>:
+ 2c: 4b ff ff e9 bl 14 <foo1>
+ 2c: R_(RBR_26|BR) .*
+ 30: 4b ff ff f5 bl 24 <foo2>
+ 30: R_(RBR_26|BR) .*
+ 34: 4b ff ff e9 bl 1c <foo1\+0x8>
+ 34: R_(RBR_26|BR) .*
+ 38: 4b ff ff f1 bl 28 <foo2\+0x4>
+ 38: R_(RBR_26|BR) .*
+ 3c: 4b ff ff c5 bl 0 <\.foo>
+ 3c: R_(RBR_26|BR) .*
+ 40: 4b ff ff ed bl 2c <\.bar>
+ 44: 48 00 00 11 bl 54 <\.frob>
+ 44: R_(RBR_26|BR) .*
+ 48: 4b ff ff d5 bl 1c <foo1\+0x8>
+ 48: R_(RBR_26|BR) .*
+ 4c: 4b ff ff ed bl 38 <\.bar\+0xc>
+ 50: 48 00 00 09 bl 58 <\.frob\+0x4>
+ 50: R_(RBR_26|BR) .*
+
+0+54 <\.frob>:
+ 54: 4b ff ff ad bl 0 <\.foo>
+ 54: R_(RBR_26|BR) .*
+ 58: 4b ff ff d5 bl 2c <\.bar>
+ 58: R_(RBR_26|BR) .*
+ 5c: 4b ff ff f9 bl 54 <\.frob>
+ 60: 4b ff ff b5 bl 14 <foo1>
+ 60: R_(RBR_26|BR) .*
+ 64: 4b ff ff c1 bl 24 <foo2>
+ 64: R_(RBR_26|BR) .*
Index: gas/testsuite/gas/ppc/xcoff-branch-1-64.d
===================================================================
--- /dev/null 2009-02-06 09:11:03.343159000 +0000
+++ gas/testsuite/gas/ppc/xcoff-branch-1-64.d 2009-03-10 13:46:12.000000000 +0000
@@ -0,0 +1,61 @@
+#as: -a64
+#source: xcoff-branch-1.s
+#objdump: -dr
+#name: XCOFF branch test 1 (64-bit)
+
+.*
+
+
+Disassembly of section \.text:
+
+0+00 <\.foo>:
+ 0: 48 00 00 29 bl 28 <foo2\+0x4>
+ 4: 48 00 00 1d bl 20 <foo1\+0xc>
+ 8: 48 00 00 0d bl 14 <foo1>
+ c: 48 00 00 19 bl 24 <foo2>
+ 10: 48 00 00 1d bl 2c <\.bar>
+ 10: R_(RBR_26|BR) .*
+
+0+14 <foo1>:
+ 14: 4b ff ff ed bl 0 <\.foo>
+ 18: 48 00 00 3d bl 54 <\.frob>
+ 18: R_(RBR_26|BR) .*
+ 1c: 4b ff ff f5 bl 10 <\.foo\+0x10>
+ 20: 48 00 00 15 bl 34 <\.bar\+0x8>
+ 20: R_(RBR_26|BR) .*
+
+0+24 <foo2>:
+ 24: 48 00 00 41 bl 64 <\.frob\+0x10>
+ 24: R_(RBR_26|BR) .*
+ 28: 4e 80 00 20 blr
+
+0+2c <\.bar>:
+ 2c: 4b ff ff e9 bl 14 <foo1>
+ 2c: R_(RBR_26|BR) .*
+ 30: 4b ff ff f5 bl 24 <foo2>
+ 30: R_(RBR_26|BR) .*
+ 34: 4b ff ff e9 bl 1c <foo1\+0x8>
+ 34: R_(RBR_26|BR) .*
+ 38: 4b ff ff f1 bl 28 <foo2\+0x4>
+ 38: R_(RBR_26|BR) .*
+ 3c: 4b ff ff c5 bl 0 <\.foo>
+ 3c: R_(RBR_26|BR) .*
+ 40: 4b ff ff ed bl 2c <\.bar>
+ 44: 48 00 00 11 bl 54 <\.frob>
+ 44: R_(RBR_26|BR) .*
+ 48: 4b ff ff d5 bl 1c <foo1\+0x8>
+ 48: R_(RBR_26|BR) .*
+ 4c: 4b ff ff ed bl 38 <\.bar\+0xc>
+ 50: 48 00 00 09 bl 58 <\.frob\+0x4>
+ 50: R_(RBR_26|BR) .*
+
+0+54 <\.frob>:
+ 54: 4b ff ff ad bl 0 <\.foo>
+ 54: R_(RBR_26|BR) .*
+ 58: 4b ff ff d5 bl 2c <\.bar>
+ 58: R_(RBR_26|BR) .*
+ 5c: 4b ff ff f9 bl 54 <\.frob>
+ 60: 4b ff ff b5 bl 14 <foo1>
+ 60: R_(RBR_26|BR) .*
+ 64: 4b ff ff c1 bl 24 <foo2>
+ 64: R_(RBR_26|BR) .*
Index: gas/testsuite/gas/ppc/aix.exp
===================================================================
--- gas/testsuite/gas/ppc/aix.exp 2009-03-10 13:38:53.000000000 +0000
+++ gas/testsuite/gas/ppc/aix.exp 2009-03-10 13:46:12.000000000 +0000
@@ -63,4 +63,6 @@ if [istarget powerpc-ibm-aix*] then {
run_dump_test "textalign-xcoff-001"
run_dump_test "textalign-xcoff-002"
+ run_dump_test "xcoff-branch-1-32"
+ run_dump_test "xcoff-branch-1-64"
}