This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] MIPS gas: Fix broken relocation sorting
- From: David Daney <ddaney at avtrex dot com>
- To: binutils at sourceware dot org
- Date: Tue, 07 Nov 2006 12:51:31 -0800
- Subject: [PATCH] MIPS gas: Fix broken relocation sorting
The problem here is that some explicit relocations were not getting
sorted properly. The %got() and %lo() were being separated by another
%got()/%lo() pair. This resulted in incorrect relocations being applied
by the linker.
At first I thought this was a GCC bug, but Ian Lance Taylor set me
straight here. For those interested, the GCC bug report is here:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29721
The root of the problem is that the relocations are against a local
symbol in another section which get converted to relocations against the
global section symbol. The relocation sorting was not done for
relocations against global symbols.
There are as far as I can see two easy ways to fix it:
1) In mips_fix_adjustable, don't allow the conversion if it would affect
a relocation that could possibly need sorting.
2) In mips_from_file, do the sorting with relocations against global
symbols also.
I chose the second option, as it looked like the exclusion of global
relocations from the sorting was probably just an optimization. The
first option would result in many %got() relocations that have no
corresponding %lo() not being converted to be against the section.
Tested with a mipsel-linux cross build with no regressions. A bootstrap
of GCC 4.2 branch is underway, but test results will not be available
for about 5 days.
OK to commit?
This bug causes bad code with both gcc-4.2 and the gcc trunk and perhaps
any gcc with explicit relocs. Would it make sense to put this on the
2.17 branch and make a 2.17.1 release before gcc-4.2 is released?
gas:
2006-11-06 David Daney <ddaney@avtrex.com>
* config/tc-mips.c (mips_frob_file): Don't check for global symbol.
gas/testsuite:
2006-11-06 David Daney <ddaney@avtrex.com>
* gas/mips/elf-rel26.s: New test.
* gas/mips/elf-rel26.d: Ditto.
* gas/mips/mips.exp: Run it.
? doc/as.info
Index: config/tc-mips.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.c,v
retrieving revision 1.359
diff -c -p -r1.359 tc-mips.c
*** config/tc-mips.c 6 Nov 2006 14:28:21 -0000 1.359
--- config/tc-mips.c 7 Nov 2006 20:21:12 -0000
*************** mips_frob_file (void)
*** 11631,11642 ****
assert (reloc_needs_lo_p (l->fixp->fx_r_type));
- /* If a GOT16 relocation turns out to be against a global symbol,
- there isn't supposed to be a matching LO. */
- if (l->fixp->fx_r_type == BFD_RELOC_MIPS_GOT16
- && !pic_need_relax (l->fixp->fx_addsy, l->seg))
- continue;
-
/* Check quickly whether the next fixup happens to be a matching %lo. */
if (fixup_has_matching_lo_p (l->fixp))
continue;
--- 11631,11636 ----
Index: testsuite/gas/mips/elf-rel26.d
===================================================================
RCS file: testsuite/gas/mips/elf-rel26.d
diff -N testsuite/gas/mips/elf-rel26.d
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/gas/mips/elf-rel26.d 7 Nov 2006 20:21:12 -0000
***************
*** 0 ****
--- 1,22 ----
+ #as: -mips32 -EL -KPIC
+ #readelf: --relocs
+ #name: MIPS ELF reloc 26
+
+ Relocation section '\.rel\.pdr' .*
+ *Offset.*
+ 00.*
+
+ Relocation section '\.rel\.text\.foo' at offset .* contains 11 entries:
+ *Offset * Info * Type * Sym\.Value * Sym\. Name
+ 0+000 * .+ * R_MIPS_HI16 * 0+0 * _gp_disp
+ 0+004 * .+ * R_MIPS_LO16 * 0+0 * _gp_disp
+ 0+014 * .+ * R_MIPS_GOT16 * 0+0 * \$LC28
+ 0+01c * .+ * R_MIPS_LO16 * 0+0 * \$LC28
+ 0+020 * .+ * R_MIPS_CALL16 * 0+0 * bar
+ 0+030 * .+ * R_MIPS_PC16 * 0+0 * \$L846
+ 0+034 * .+ * R_MIPS_GOT16 * 0+0 * \$LC27
+ 0+038 * .+ * R_MIPS_PC16 * 0+0 * \$L848
+ 0+048 * .+ * R_MIPS_PC16 * 0+0 * \$L925
+ 0+010 * .+ * R_MIPS_GOT16 * 0+0 * \.rodata\.foo
+ 0+05c * .+ * R_MIPS_LO16 * 0+0 * \.rodata\.foo
+ #pass
Index: testsuite/gas/mips/elf-rel26.s
===================================================================
RCS file: testsuite/gas/mips/elf-rel26.s
diff -N testsuite/gas/mips/elf-rel26.s
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/gas/mips/elf-rel26.s 7 Nov 2006 20:21:12 -0000
***************
*** 0 ****
--- 1,62 ----
+ .section .text.foo,"axG",@progbits,foo,comdat
+ .align 2
+ .weak foo
+ .ent foo
+ .type foo, @function
+ foo:
+ $LFB308:
+ .frame $fp,136,$31 # vars= 72, regs= 10/0, args= 16, gp= 8
+ .mask 0xc0ff0000,-4
+ .fmask 0x00000000,0
+ .set noreorder
+ .cpload $25
+
+ .set nomacro
+ bne $3,$0,$L924
+ lw $25,%got($L874)($28)
+ .set macro
+ .set reorder
+ lw $5,%got($LC28)($28)
+ lw $4,136($fp)
+ addiu $5,$5,%lo($LC28)
+ lw $25,%call16(bar)($28)
+ .set noreorder
+ .set nomacro
+ jalr $25
+ li $6,-1 # 0xffffffffffffffff
+ .set macro
+ .set reorder
+ lw $25,64($fp)
+ .set noreorder
+ .set nomacro
+ bne $25,$0,$L846
+ lw $5,%got($LC27)($28)
+ b $L848
+ sw $0,68($fp)
+ .set macro
+ .set reorder
+ $L920:
+ lb $3,0($18)
+ li $2,59 # 0x3b
+ .set noreorder
+ .set nomacro
+ beq $3,$2,$L925
+ lw $25,76($fp)
+ b $L920
+ addiu $18,$18,1
+ .set macro
+ .set reorder
+
+ $L924:
+ sll $2,$2,2
+ addiu $25,$25,%lo($L874)
+ addu $2,$2,$25
+ lw $3,0($2)
+ addu $3,$3,$28
+ j $3
+ .end foo
+ .section .rodata.foo,"aG",@progbits,foo,comdat
+ .align 2
+ .align 2
+ $L874:
+ .gpword $L924
Index: testsuite/gas/mips/mips.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/mips.exp,v
retrieving revision 1.125
diff -c -p -r1.125 mips.exp
*** testsuite/gas/mips/mips.exp 2 Nov 2006 15:20:31 -0000 1.125
--- testsuite/gas/mips/mips.exp 7 Nov 2006 20:21:12 -0000
*************** if { [istarget mips*-*-vxworks*] } {
*** 687,692 ****
--- 687,693 ----
run_dump_test "elf-rel25"
run_dump_test "elf-rel25a"
+ run_dump_test "elf-rel26"
if { !$no_mips16 } {
run_dump_test "${tmips}mips${el}16-e"