forked from Imagelibrary/binutils-gdb
MIPS/BFD: Fix RELA handling of borrow in the generic linker
Fix an issue with `_bfd_mips_elf_generic_reloc' not taking into account any borrow from the lower part in the handling of relocations of the HI/LO kind and resulting in incorrect calculations made for RELA targets in the generic used for non-ELF output such as S-records. This doesn't trigger for REL targets because they call `_bfd_mips_elf_generic_reloc' indirectly from `_bfd_mips_elf_lo16_reloc' so as to obtain a complete 32-bit addend from relocation pairs and in calculating the addend the latter function uses a hack to work around the lack of borrow handling in the former function. The MIPS/ELF linker is unaffected as it uses its own calculations. Correct the calculation of the relevant partial relocations made in `_bfd_mips_elf_generic_reloc' then to take the borrow into account and remove the hack from `_bfd_mips_elf_lo16_reloc' as no longer needed. Add generic linker test cases accordingly expecting the same disassembly from srec output produced as from ELF output produced by the MIPS/ELF linker.
This commit is contained in:
@@ -2599,15 +2599,13 @@ _bfd_mips_elf_lo16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
|
||||
addend is adjusted for the fact that the low part is sign
|
||||
extended. For example, an addend of 0x38000 would have 0x0004 in
|
||||
the high part and 0x8000 (=0xff..f8000) in the low part.
|
||||
To extract the actual addend, calculate (a)
|
||||
To extract the actual addend, calculate
|
||||
((hi & 0xffff) << 16) + ((lo & 0xffff) ^ 0x8000) - 0x8000.
|
||||
We will be applying (symbol + addend) & 0xffff to the low insn,
|
||||
and we want to apply (b) (symbol + addend + 0x8000) >> 16 to the
|
||||
and we want to apply (symbol + addend + 0x8000) >> 16 to the
|
||||
high insn (the +0x8000 adjusting for when the applied low part is
|
||||
negative). Substituting (a) into (b) and recognising that
|
||||
(hi & 0xffff) is already in the high insn gives a high part
|
||||
addend adjustment of (lo & 0xffff) ^ 0x8000. */
|
||||
vallo = (bfd_get_32 (abfd, location) & 0xffff) ^ 0x8000;
|
||||
negative). */
|
||||
vallo = ((bfd_get_32 (abfd, location) & 0xffff) ^ 0x8000) - 0x8000;
|
||||
_bfd_mips_elf_reloc_shuffle (abfd, reloc_entry->howto->type, false,
|
||||
location);
|
||||
|
||||
@@ -2707,6 +2705,29 @@ _bfd_mips_elf_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
|
||||
/* Add in the separate addend, if any. */
|
||||
val += reloc_entry->addend;
|
||||
|
||||
/* The high 16 bits of the addend are stored in the high insn, the
|
||||
low 16 bits in the low insn, but there is a catch: You can't
|
||||
just concatenate the high and low parts. The high part of the
|
||||
addend is adjusted for the fact that the low part is sign
|
||||
extended. For example, an addend of 0x38000 would have 0x0004 in
|
||||
the high part and 0x8000 (=0xff..f8000) in the low part.
|
||||
We will be applying (symbol + addend) & 0xffff to the low insn,
|
||||
and we want to apply (symbol + addend + 0x8000) >> 16 to the
|
||||
high insn (the +0x8000 adjusting for when the applied low part is
|
||||
negative). Analogously for the higher parts of a 64-bit addend. */
|
||||
if (reloc_entry->howto->bitsize == 16
|
||||
&& reloc_entry->howto->rightshift % 16 == 0)
|
||||
#ifdef BFD64
|
||||
val += 0x800080008000ULL >> (48 - reloc_entry->howto->rightshift);
|
||||
#else
|
||||
{
|
||||
if (reloc_entry->howto->rightshift <= 16)
|
||||
val += 0x8000 >> (16 - reloc_entry->howto->rightshift);
|
||||
else
|
||||
abort ();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Add VAL to the relocation field. */
|
||||
_bfd_mips_elf_reloc_unshuffle (abfd, reloc_entry->howto->type, false,
|
||||
location);
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
#ld: -Tmips-hilo.ld -e 0x500000 -N
|
||||
#notarget: mips*el-ps2-elf*
|
||||
|
||||
.*: file format elf.*mips.*
|
||||
.*: file format (:?elf.*mips.*|srec)
|
||||
|
||||
Disassembly of section \.text:
|
||||
Disassembly of section \.(:?text|sec1):
|
||||
|
||||
0*500000 <[^>]*>:
|
||||
*500000: 41a1 0000 lui at,0x0
|
||||
|
||||
8
ld/testsuite/ld-mips-elf/micromips-hilo-srec-n32.d
Normal file
8
ld/testsuite/ld-mips-elf/micromips-hilo-srec-n32.d
Normal file
@@ -0,0 +1,8 @@
|
||||
#name: R_MICROMIPS_HI16 and R_MICROMIPS_LO16 relocs srec n32
|
||||
#source: ../../../gas/testsuite/gas/mips/mips-hilo.s
|
||||
#source: mips-hilo.s
|
||||
#as: -mmicromips -march=mips64r2
|
||||
#objdump: -m mips:micromips -j .sec1 -D
|
||||
#ld: --oformat=srec -Tmips-hilo.ld -e 0x500000 -N
|
||||
#notarget: mips*el-ps2-elf*
|
||||
#dump: micromips-hilo.d
|
||||
8
ld/testsuite/ld-mips-elf/micromips-hilo-srec-n64.d
Normal file
8
ld/testsuite/ld-mips-elf/micromips-hilo-srec-n64.d
Normal file
@@ -0,0 +1,8 @@
|
||||
#name: R_MICROMIPS_HI16 and R_MICROMIPS_LO16 relocs srec n64
|
||||
#source: ../../../gas/testsuite/gas/mips/mips-hilo-n64.s
|
||||
#source: mips-hilo.s
|
||||
#as: -mmicromips -march=mips64r2
|
||||
#objdump: -m mips:micromips -j .sec1 -D
|
||||
#ld: --oformat=srec -Tmips-hilo.ld -e 0x500000 -N
|
||||
#notarget: mips*el-ps2-elf*
|
||||
#dump: micromips-hilo-n64.d
|
||||
8
ld/testsuite/ld-mips-elf/micromips-hilo-srec.d
Normal file
8
ld/testsuite/ld-mips-elf/micromips-hilo-srec.d
Normal file
@@ -0,0 +1,8 @@
|
||||
#name: R_MICROMIPS_HI16 and R_MICROMIPS_LO16 relocs srec
|
||||
#source: ../../../gas/testsuite/gas/mips/mips-hilo.s
|
||||
#source: mips-hilo.s
|
||||
#as: -mmicromips -march=mips32r2
|
||||
#objdump: -m mips:micromips -j .sec1 -D
|
||||
#ld: --oformat=srec -Tmips-hilo.ld -e 0x500000 -N
|
||||
#notarget: mips*el-ps2-elf*
|
||||
#dump: micromips-hilo.d
|
||||
@@ -6,9 +6,9 @@
|
||||
#ld: -Tmips-hilo.ld -e 0x500000 -N
|
||||
#notarget: mips*el-ps2-elf*
|
||||
|
||||
.*: file format elf.*mips.*
|
||||
.*: file format (:?elf.*mips.*|srec)
|
||||
|
||||
Disassembly of section \.text:
|
||||
Disassembly of section \.(:?text|sec1):
|
||||
|
||||
0*500000 <[^>]*>:
|
||||
*500000: 41a4 0000 lui a0,0x0
|
||||
|
||||
@@ -816,14 +816,41 @@ run_dump_test "mode-change-error-1"
|
||||
|
||||
run_dump_test_o32 "mips16-hilo" noarch
|
||||
run_dump_test_n32 "mips16-hilo-n32" noarch
|
||||
run_dump_test_o32 "mips16-hilo-srec" \
|
||||
[list noarch \
|
||||
[list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]]
|
||||
run_dump_test_n32 "mips16-hilo-srec-n32" \
|
||||
[list noarch \
|
||||
[list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]]
|
||||
run_dump_test_o32 "mips16e2-hilo" noarch
|
||||
run_dump_test_n32 "mips16e2-hilo-n32" noarch
|
||||
run_dump_test_o32 "mips16e2-hilo-srec" \
|
||||
[list noarch \
|
||||
[list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]]
|
||||
run_dump_test_n32 "mips16e2-hilo-srec-n32" \
|
||||
[list noarch \
|
||||
[list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]]
|
||||
run_dump_test_o32 "mips-hilo"
|
||||
run_dump_test_n32 "mips-hilo-n32"
|
||||
run_dump_test_n64 "mips-hilo-n64"
|
||||
run_dump_test_o32 "mips-hilo-srec" \
|
||||
[list [list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]]
|
||||
run_dump_test_n32 "mips-hilo-srec-n32" \
|
||||
[list [list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]]
|
||||
run_dump_test_n64 "mips-hilo-srec-n64" \
|
||||
[list [list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]]
|
||||
run_dump_test_o32 "micromips-hilo" noarch
|
||||
run_dump_test_n32 "micromips-hilo-n32" noarch
|
||||
run_dump_test_n64 "micromips-hilo-n64" noarch
|
||||
run_dump_test_o32 "micromips-hilo-srec" \
|
||||
[list noarch \
|
||||
[list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]]
|
||||
run_dump_test_n32 "micromips-hilo-srec-n32" \
|
||||
[list noarch \
|
||||
[list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]]
|
||||
run_dump_test_n64 "micromips-hilo-srec-n64" \
|
||||
[list noarch \
|
||||
[list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]]
|
||||
|
||||
if { $linux_gnu } {
|
||||
run_dump_test_n32 "textrel-1"
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
#objdump: -d
|
||||
#ld: -Tmips-hilo.ld -e 0x500000 -N
|
||||
|
||||
.*: file format elf.*mips.*
|
||||
.*: file format (:?elf.*mips.*|srec)
|
||||
|
||||
Disassembly of section \.text:
|
||||
Disassembly of section \.(:?text|sec1):
|
||||
|
||||
0*500000 <[^>]*>:
|
||||
*500000: 3c010000 lui at,0x0
|
||||
|
||||
6
ld/testsuite/ld-mips-elf/mips-hilo-srec-n32.d
Normal file
6
ld/testsuite/ld-mips-elf/mips-hilo-srec-n32.d
Normal file
@@ -0,0 +1,6 @@
|
||||
#name: R_MIPS_HI16 and R_MIPS_LO16 relocs srec n32
|
||||
#source: ../../../gas/testsuite/gas/mips/mips-hilo.s
|
||||
#source: mips-hilo.s
|
||||
#objdump: -m mips:4000 -j .sec1 -D
|
||||
#ld: --oformat=srec -Tmips-hilo.ld -e 0x500000 -N
|
||||
#dump: mips-hilo.d
|
||||
6
ld/testsuite/ld-mips-elf/mips-hilo-srec-n64.d
Normal file
6
ld/testsuite/ld-mips-elf/mips-hilo-srec-n64.d
Normal file
@@ -0,0 +1,6 @@
|
||||
#name: R_MIPS_HI16 and R_MIPS_LO16 relocs srec n64
|
||||
#source: ../../../gas/testsuite/gas/mips/mips-hilo-n64.s
|
||||
#source: mips-hilo.s
|
||||
#objdump: -m mips:4000 -j .sec1 -D
|
||||
#ld: --oformat=srec -Tmips-hilo.ld -e 0x500000 -N
|
||||
#dump: mips-hilo-n64.d
|
||||
6
ld/testsuite/ld-mips-elf/mips-hilo-srec.d
Normal file
6
ld/testsuite/ld-mips-elf/mips-hilo-srec.d
Normal file
@@ -0,0 +1,6 @@
|
||||
#name: R_MIPS_HI16 and R_MIPS_LO16 relocs srec
|
||||
#source: ../../../gas/testsuite/gas/mips/mips-hilo.s
|
||||
#source: mips-hilo.s
|
||||
#objdump: -m mips:3000 -j .sec1 -D
|
||||
#ld: --oformat=srec -Tmips-hilo.ld -e 0x500000 -N
|
||||
#dump: mips-hilo.d
|
||||
@@ -4,9 +4,9 @@
|
||||
#objdump: -d
|
||||
#ld: -Tmips-hilo.ld -e 0x500000 -N
|
||||
|
||||
.*: file format elf.*mips.*
|
||||
.*: file format (:?elf.*mips.*|srec)
|
||||
|
||||
Disassembly of section \.text:
|
||||
Disassembly of section \.(:?text|sec1):
|
||||
|
||||
0*500000 <[^>]*>:
|
||||
*500000: 3c040000 lui a0,0x0
|
||||
|
||||
7
ld/testsuite/ld-mips-elf/mips16-hilo-srec-n32.d
Normal file
7
ld/testsuite/ld-mips-elf/mips16-hilo-srec-n32.d
Normal file
@@ -0,0 +1,7 @@
|
||||
#name: R_MIPS16_HI16 and R_MIPS16_LO16 relocs srec n32
|
||||
#source: ../../../gas/testsuite/gas/mips/mips16-hilo.s
|
||||
#source: mips-hilo.s
|
||||
#as: -march=mips3
|
||||
#objdump: -mmips:16 -j .sec1 -D
|
||||
#ld: --oformat=srec -Tmips-hilo.ld -e 0x500000 -N
|
||||
#dump: mips16-hilo.d
|
||||
7
ld/testsuite/ld-mips-elf/mips16-hilo-srec.d
Normal file
7
ld/testsuite/ld-mips-elf/mips16-hilo-srec.d
Normal file
@@ -0,0 +1,7 @@
|
||||
#name: R_MIPS16_HI16 and R_MIPS16_LO16 relocs srec
|
||||
#source: ../../../gas/testsuite/gas/mips/mips16-hilo.s
|
||||
#source: mips-hilo.s
|
||||
#as: -march=mips1
|
||||
#objdump: -mmips:16 -j .sec1 -D
|
||||
#ld: --oformat=srec -Tmips-hilo.ld -e 0x500000 -N
|
||||
#dump: mips16-hilo.d
|
||||
@@ -5,9 +5,9 @@
|
||||
#objdump: -mmips:16 -dr
|
||||
#ld: -Tmips-hilo.ld -e 0x500000 -N
|
||||
|
||||
.*: file format elf.*mips.*
|
||||
.*: file format (:?elf.*mips.*|srec)
|
||||
|
||||
Disassembly of section .text:
|
||||
Disassembly of section \.(:?text|sec1):
|
||||
|
||||
0*500000 <[^>]*>:
|
||||
*500000: 6c00 li a0,0
|
||||
|
||||
8
ld/testsuite/ld-mips-elf/mips16e2-hilo-srec-n32.d
Normal file
8
ld/testsuite/ld-mips-elf/mips16e2-hilo-srec-n32.d
Normal file
@@ -0,0 +1,8 @@
|
||||
#name: MIPS16e2 R_MIPS16_HI16 and R_MIPS16_LO16 relocs srec n32
|
||||
#source: ../../../gas/testsuite/gas/mips/mips-hilo.s
|
||||
#source: mips-hilo.s
|
||||
#as: -mips16 -mmips16e2 -march=mips64r2
|
||||
#objdump: -mmips:16 -j .sec1 -D
|
||||
#ld: --oformat=srec -Tmips-hilo.ld -e 0x500000 -N
|
||||
#notarget: mips*el-ps2-elf*
|
||||
#dump: mips16e2-hilo.d
|
||||
8
ld/testsuite/ld-mips-elf/mips16e2-hilo-srec.d
Normal file
8
ld/testsuite/ld-mips-elf/mips16e2-hilo-srec.d
Normal file
@@ -0,0 +1,8 @@
|
||||
#name: MIPS16e2 R_MIPS16_HI16 and R_MIPS16_LO16 relocs srec
|
||||
#source: ../../../gas/testsuite/gas/mips/mips-hilo.s
|
||||
#source: mips-hilo.s
|
||||
#as: -mips16 -mmips16e2 -march=mips32r2
|
||||
#objdump: -mmips:16 -j .sec1 -D
|
||||
#ld: --oformat=srec -Tmips-hilo.ld -e 0x500000 -N
|
||||
#notarget: mips*el-ps2-elf*
|
||||
#dump: mips16e2-hilo.d
|
||||
@@ -6,9 +6,9 @@
|
||||
#ld: -Tmips-hilo.ld -e 0x500000 -N
|
||||
#notarget: mips*el-ps2-elf*
|
||||
|
||||
.*: file format elf.*mips.*
|
||||
.*: file format (:?elf.*mips.*|srec)
|
||||
|
||||
Disassembly of section \.text:
|
||||
Disassembly of section \.(:?text|sec1):
|
||||
|
||||
0*500000 <[^>]*>:
|
||||
*500000: f000 6c20 lui a0,0x0
|
||||
|
||||
Reference in New Issue
Block a user